Perl Brasil

Pesquisar

Documentação

Artigos

Planeta

Eventos


FISL 10 - Software Livre, a tecnologia que liberta

Comunidade

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 anterior

  binmode 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;

Conclusão

Se você está chamando encode, decode, upgrade ou qualquer um dos métodos do módulo Encode ou utf8, é um sinal de que você está fazendo alguma coisa errada, e que cedo ou tarde você vai misturar as coisas e vai ter caracteres com erro de codificação. Em Perl você não deve se preocupar com codificação para além de "marcar" as suas entradas e saídas de dados.

Comentários