Estoy teniendo algunos resultados interesantes tratando de discernir las diferencias entre usar Encode::decode("utf8", $var)
y utf8::decode($var)
. Ya he descubierto que llamar al anterior varias veces en una variable eventualmente dará como resultado un error "No se puede decodificar la cadena con caracteres anchos en ...", mientras que el último método funcionará felizmente tantas veces como se desee, simplemente devolviendo falso.Perl: utf8 :: decodificar vs. Codificar :: decodificar
Lo que tengo problemas para entender es cómo la función length
arroja resultados diferentes según el método que utilice para decodificar. El problema surge porque estoy tratando con texto utf8 "doblemente codificado" de un archivo externo. Para demostrar este problema, creé un archivo de texto "test.txt" con los siguientes caracteres Unicode en una línea: U + 00e8, U + 00ab, U + 0086, U + 000a. Estos caracteres Unicode son la doble codificación del carácter Unicode U + 8acb, junto con un carácter de nueva línea. El archivo fue codificado en el disco en UTF8. Luego ejecutar el siguiente script Perl:
#!/usr/bin/perl
use strict;
use warnings;
require "Encode.pm";
require "utf8.pm";
open FILE, "test.txt" or die $!;
my @lines = <FILE>;
my $test = $lines[0];
print "Length: " . (length $test) . "\n";
print "utf8 flag: " . utf8::is_utf8($test) . "\n";
my @unicode = (unpack('U*', $test));
print "Unicode:\[email protected]\n";
my @hex = (unpack('H*', $test));
print "Hex:\[email protected]\n";
print "==============\n";
$test = Encode::decode("utf8", $test);
print "Length: " . (length $test) . "\n";
print "utf8 flag: " . utf8::is_utf8($test) . "\n";
@unicode = (unpack('U*', $test));
print "Unicode:\[email protected]\n";
@hex = (unpack('H*', $test));
print "Hex:\[email protected]\n";
print "==============\n";
$test = Encode::decode("utf8", $test);
print "Length: " . (length $test) . "\n";
print "utf8 flag: " . utf8::is_utf8($test) . "\n";
@unicode = (unpack('U*', $test));
print "Unicode:\[email protected]\n";
@hex = (unpack('H*', $test));
print "Hex:\[email protected]\n";
Esto da el siguiente resultado:
Length: 7 utf8 flag: Unicode: 195 168 194 171 194 139 10 Hex: c3a8c2abc28b0a ============== Length: 4 utf8 flag: 1 Unicode: 232 171 139 10 Hex: c3a8c2abc28b0a ============== Length: 2 utf8 flag: 1 Unicode: 35531 10 Hex: e8ab8b0a
Esto es lo que se esperaría. La longitud es originalmente 7 porque perl cree que $ test es solo una serie de bytes. Después de decodificar una vez, Perl sabe que $ test es una serie de caracteres que están codificados en utf8 (es decir, en lugar de devolver una longitud de 7 bytes, Perl devuelve una longitud de 4 caracteres, aunque $ test todavía tiene 7 bytes en la memoria). Después de la segunda decodificación, $ test contiene 4 bytes interpretados como 2 caracteres, que es lo que esperaría ya que Encode :: decode tomó los 4 puntos de código y los interpretó como bytes codificados en utf8, lo que resulta en 2 caracteres. Lo extraño es cuando modifico el código para llamar a utf8 :: decode en su lugar (reemplace all $ test = Encode :: decode ("utf8", $ test); con utf8 :: decode ($ test))
This da salida casi idéntico, sólo el resultado de longitud difiere:
Length: 7 utf8 flag: Unicode: 195 168 194 171 194 139 10 Hex: c3a8c2abc28b0a ============== Length: 4 utf8 flag: 1 Unicode: 232 171 139 10 Hex: c3a8c2abc28b0a ============== Length: 4 utf8 flag: 1 Unicode: 35531 10 Hex: e8ab8b0a
parece que perl primera cuenta los bytes antes de decodificar (como se esperaba), y luego cuenta los caracteres después de la primera decodificación, pero luego cuenta los bytes de nuevo después de la segunda decodificación (no esperada). ¿Por qué ocurriría este cambio? ¿Hay un lapso en mi comprensión de cómo funcionan estas funciones de decodificación?
Gracias, Matt
¿Alguna razón por la cual usted está 'requiriendo módulos en vez de' usarlos '? –
No utilicé
use
utf8 porque al hacerlo perl dice que su código está codificado en utf8, lo que no necesito (http://perldoc.perl.org/utf8.html). Supongo que podría haber codificadouse
d, pero sucedió que no. – Matt