Desconozco cómo son tus programas, así que no sé qué transformaciones haces.
Lo que sorprende a los programadores, es que, cuando pasan de un sistema a otro, o incluso en el mismo sistema hardware y le actualizan el sistema software, sus programas dejan de funcionar o funcionan mal. Y todo porque el sistema de codificación de caracteres ha cambiado o es distinto.
En ese momento se dan cuenta de que hasta ahora trataban a los ficheros como un flujo de bytes, no como un flujo de caracteres.
Tú siempre puedes tratar a un fichero como un flujo de bytes. Entonces lo abres, escribes en él, haces búsquedas, transformaciones, etc. Mientras no te metas con los caracteres tildados y "extraños", todo va bien. El problema aparece si un día necesitas buscar por un carácter tildado. Bueno, en principio lo resuelves poniendo 'use utf8;' en el programa, y de esa manera, Perl sabe que la 'ñ' que has puesto en tu programa, en lugar de ser un único byte 241 en codificación latin1, son dos bytes en codificación UTF8 (y contando que estés en un editor que trabaje en UTF8, también). Si luego sigues haciendo las operaciones anteriores con los ficheros, Perl usará esos dos bytes cada vez que quieras buscar/sustituir esa 'ñ'. Pero sigues
trabajando en bytes.
A partir de Perl 5.8, se dio un impulso especial a todo el tema del tratamiento de ficheros y flujos de entrada y de salida, basada en caracteres. De hecho, Perl siempre trabaja, internamente, en caracteres Unicode, salvo que indiquemos que queremos trabajar en bytes. Por eso, es importantísimo,
siempre, indicar en qué codificación vamos a leer qué fichero y en cuál vamos a escribir. Perl se encargará de hacer las transformaciones entre las codificaciones de caracteres.
Yo, desde hace mucho tiempo, trabajo en sistemas operativos con codificación UTF8. Y los editores de programas y texto y terminales de línea de comando, lo mismo (hace unos pocos años, era un lío: cada cosa tenía su propia codificación).
Para mis programas Perl, entonces, colocaba siempre estas líneas, al principio:
Using perl Syntax Highlighting
#!/usr/bin/perl
use Modern::Perl; # Somos modernos
use utf8; # este programa está escrito en utf8
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
El módulo
Modern::Perl activa el 'strict', el 'warning' y las nuevas 'features' de Perl v5.10. Y el 'utf8' indica que voy a usar esa codificación en el resto del programa.
Hoy en día uso una combinación mejor:
Using perl Syntax Highlighting
#!/usr/bin/perl
use common::sense; # Hay que tener sentido común
use open qw(:utf8 :std); # la salida y la entrada estándar serán en utf8
use autodie; # es mejor morir que regresar con deshonor (proverbio Klingon)
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
El módulo
common::sense hace lo mismo que el Modern::Perl, pero además activa el utf8, y convierte algunos
warnings en errores (que es lo que prefiero: que el programa falle si ocurre algo extraño).
Lo importante es lo que sigue: con el
pragma open estoy indicando que, por defecto, todos los ficheros que voy a abrir estarán en codificación utf8. Y eso incluye a STDIN, STDOUT, STDERR (con el ':std').
Ejemplo.
Supongamos que estemos en un sistema y terminal con codificación UTF8. Hacemos las siguientes pruebas:
explorer@casa:~> perl -le 'print "á"'
áBueno, nada sorprendente, ¿no? le decimos a Perl que saque 'á' y eso hace.
explorer@casa:~> perl -le 'use utf8; print "á"'
�¡Oops! ¿Qué pasa? Ahora hemos indicado que nuestro programa está escrito en UTF8, pero no sale nuestra letra. Y debería, porque estamos en una terminal con esa codificación.
explorer@casa:~> perl -le 'use utf8; print "á"' |hexdump -C
00000000 e1 0a |..|
00000002Perl está emitiendo un 'á'
pero en codificación latin1 (un byte 241). Claro: esa es la codificación por defecto en Perl.
explorer@casa:~> perl -le 'print "á"'|hexdump -C
00000000 c3 a1 0a |...|
00000003Y ahora ya está todo más claro: si no decimos nada, al poner 'á' en el programa, Perl
no ve una 'a', sino que solo
ve dos bytes (0xc3 y 0xa1), y al sacarlos por la pantalla, es
el propio terminal nuestro el que traduce esos dos bytes a uno solo.
Al poner el 'use utf8;', Perl ahora ya sabe que esos dos bytes, en realidad, equivalen a un solo carácter (¡Ojo! hay que prestar atención a las palabras: 'byte' != 'carácter') Perl, entonces, transforma esos dos bytes a un único carácter Unicode, de forma interna.
Y a la hora de salida, Perl sabe que tiene que sacar los caracteres en codificación latin1 (la de defecto), así que el carácter 'á', en Unicode, se transforma en una 'á' en latin1 (un byte 241).
Entonces... no nos vale solo con decir que el programa contiene caracteres UTF8, sino que queremos que la salida también sea en esa codificación.
explorer@casa:~> perl -le 'use utf8; use open qw(:utf8 :std); print "á"'
á
explorer@casa:~> perl -le 'use utf8; use open qw(:utf8 :std); print "á"' |hexdump -C
00000000 c3 a1 0a |...|
00000003
Ahora, con la ayuda de
open, Perl ya sabe que debe sacar los caracteres en UTF8, y eso es lo que hace.
Hoy, con los nuevos Perl, se puede poner de forma abreviada:
explorer@casa:~> perl -CSDL -E 'use utf8; say "á"'Con la línea que pones, estás indicando en qué codificación vas a leer $rutafichero, lo cual es lo correcto. Y esto hay que hacerlo en todos los open(), o usar el
pragma open para indicar las codificaciones por defecto para todos los open().
Más información
perldoc open.