Bienvenido a los foros de Perl en Español, Dgrande.
Supongamos que tenemos el fichero ucs2.txt:
Esto es una prueba de ucs2. áéíóúñÑque internamente, vemos que está codificado en UCS2:
Using text Syntax Highlighting
explorer@joaquin:~/Documents/Desarrollo> hexdump -C ucs2.txt
00000000 ff fe 45 00 73 00 74 00 6f 00 20 00 65 00 73 00 |..E.s.t.o. .e.s.|
00000010 20 00 75 00 6e 00 61 00 20 00 70 00 72 00 75 00 | .u.n.a. .p.r.u.|
00000020 65 00 62 00 61 00 20 00 64 00 65 00 20 00 75 00 |e.b.a. .d.e. .u.|
00000030 63 00 73 00 32 00 2e 00 20 00 e1 00 e9 00 ed 00 |c.s.2... .......|
00000040 f3 00 fa 00 f1 00 d1 00 0a 00 |..........|
0000004a
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
Incluso tiene la cabecera típica de la codificación, en los dos primeros bytes.
Este programa nos lo cambia a UTF8:
Using perl Syntax Highlighting
#!/usr/bin/perl
open my $UCS2, '<:encoding(UCS-2LE)', 'ucs2.txt' or die "ERROR: $!\n";
open my $UTF8, '>:encoding(UTF-8)', 'utf8.txt' or die "ERROR: $!\n";
read $UCS2, my $buffer, -s 'ucs2.txt';
print $UTF8 $buffer;
close $UCS2;
close $UTF8;Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Vemos la salida:
Using text Syntax Highlighting
explorer@joaquin:~/Documents/Desarrollo> hexdump -C utf8.txt
00000000 ef bb bf 45 73 74 6f 20 65 73 20 75 6e 61 20 70 |...Esto es una p|
00000010 72 75 65 62 61 20 64 65 20 75 63 73 32 2e 20 c3 |rueba de ucs2. .|
00000020 a1 c3 a9 c3 ad c3 b3 c3 ba c3 b1 c3 91 0a |..............|
0000002e
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
Observa que también te respeta las cabeceras de los ficheros.
Obtendrías el mismo resultado si lo hicieras usando el open pragma:
Using perl Syntax Highlighting
use open IN => ':encoding(UCS-2LE)', OUT => ':encoding(UTF-8)';
open my $UCS2, '<', 'ucs2.txt' or die "ERROR: $!\n";
open my $UTF8, '>', 'utf8.txt' or die "ERROR: $!\n";
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Y usando Encode:
Using perl Syntax Highlighting
#!/usr/bin/perl
use Encode qw(from_to);
open my $UCS2, '<', 'ucs2.txt' or die "ERROR: $!\n";
open my $UTF8, '>', 'utf8.txt' or die "ERROR: $!\n";
read $UCS2, my $buffer, -s 'ucs2.txt';
from_to($buffer,'ucs-2le','utf8');
print $UTF8 $buffer;
close $UCS2;
close $UTF8;
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Recuerda que la codificación por defecto, en Perl, es la ISO-8859-1, y Perl la usará, bien a la entrada y/o a la salida, si no le decimos lo contrario. O si tratamos los octetos leídos como una determinada codificación. Si queremos asegurarnos de que Perl no va a tocar nada mientras leemos o escribimos, añadimos las líneas
Using perl Syntax Highlighting
binmode $UCS2;
binmode $UTF8;
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
justo después de los open(). También se pueden indicar las codificaciones ahí.
Fíjate también que he usado read() para leer el fichero. El comportamiento de read() es también distinto según la codificación del fichero: por defecto, es en bytes, pero si definimos una codificación distinta, el comportamiento será en caracteres.
En los códigos indico a read que lea
-s 'ucs2.txt', que es el tamaño del fichero en bytes. Pero si yo he definido antes (en el open o en open pragma, binmode, etc) que es otra codificación distinta, intentará leer caracteres. Y sabemos que esas dos cifras son distintas: el fichero ucs2.txt ocupa 74 bytes en mi disco, pero solo tiene 36 caracteres. read() intentará leer 74 caracteres, pero solo leerá 36. No importa, porque sé que el número de bytes siempre es mayor que el de caracteres. Pasaría lo mismo con otra codificación: en utf8 el fichero ocupa 46 bytes.