r1 - 08 Jan 2009 - DanielRuoso
Como usar UTF8 e outros encodings corretamente
Problema
Muitas vezes você precisa lidar com diversos encodings ao longo de um programa. Intuitivamente as pessoas tentam codificar e decodificar manualmente as strings, o que invariavelmente leva a problemas.Solução
O Perl tem o "IO Layer" que permite que você estabeleça regras de processamento para cada dado de entrada ou saída no seu programa, dessa forma você só precisa dizer o encoding daquilo que você lê e escreve, e nunca fazer conversões manuais.Discussão
Lendo e Escrevendo de Arquivos
O segredo para trabalhar corretamente com arquivos é dizer qual é o encoding do arquivo de onde você vai ler ou onde você vai escrever. Existem duas "tags" para identificar o encoding do arquivo, a primeira é a específica para utf8.open my $input, '<:utf8', 'arquivo.txt'; open my $output, '>:utf8', 'arquivo.txt';A outra tag é uma tag genérica, que permite você dizer qualquer encoding (inclusive utf8):
open my $input, '<:encoding(iso8859-1)', 'arquivo.txt' open my $output, '>:encoding(iso8859-1)', 'arquivo.txt'Uma vez que você faça isso em todos os arquivos, tudo vai funcionar automaticamente, e todas as conversões serão realizadas implicitamente, dependendo de onde você lê e para onde você escreve.
Lendo e Escrevendo de FileHandles? (STDIN, STDOUT, Sockets etc)
Se o filehandle não é aberto com "open", você pode definir o atributo usando o comando binmode, com as mesmas tags do tópico anteriorbinmode STDOUT, ':utf8'; binmode STDIN, ':encoding(iso8859-1)';
Obtendo dados de uma requisição HTTP
Qualquer um dos módulos que eu consigo pensar que tratam de HTTP, CGI, mod_perl já "marcam" as strings com a codificação de origem, ou seja, você não precisa se preocupar. Se houver inconsistência do outro lado (mandando numa codificação diferente que sinaliza), aí você terá que tratar caso a caso, e provavelmente vai ser instável.Lendo e Escrevendo em Banco de Dados
Se você estiver usando o PostgreSQL? , que é um banco de verdade, ele e o DBD::pg já vão fazer tudo por você. Você pode usar sem medo. Agora, se você estiver usando o MySQL? (e não há um bom motivo pra isso), você vai ter que fazer duas coisas (e mesmo assim não vai funcionar pra tudo):
my $dbi = DBI->connect('db:mysql:....');
$dbi->do('SET NAMES "UTF8"');
$dbi->{mysql_enable_utf8} = 1;
Depois disso você deve conseguir trabalhar sem muitos problemas.
Strings no código fonte
Esse é um ponto comum de problemas, porque para o código fonte, o perl só aceita duas codificações, ou é iso8859-1, ou é utf8. Então é sempre melhor usar utf8 (descubra como configurar o seu editor para ter certeza que está na codificação certa). Depois disso lembre-se de adicionar mais um elemento no seu mantra:use strict; use warnings; use utf8;

