Cuidando de Caracteres

De Wiki REDDES

Tabla de contenidos

Cuidando de caracteres especiais

Introdução

Esta no cotidiano de todo analista os problemas com conjunto de caracteres e codificação de caracteres. Os símbolos estranhos podem vir dos mais diferentes lugares: uma configuração desconhecida ou esquecida no Apache ou PHP; interfaces que exibem documentos de bases incompatíveis ou as misteriosas transformações com XSL. Contudo é possível reduzir a quantidade de problemas, assim como a complexidade, somente não deixando que motivos citados não aconteçam todos de uma vez.

Objetivo

Nesta página pretende-se agregar conceitos dos conjuntos de caracteres e formas de exibí-los corretamente utilizando as ferramentas e tecnologias disponíveis na BIREME.

Unicode

Deve-se ter noção do objetivo deste conjunto de caracteres e como ele influencia algumas siglas que soam familiar para alguns desenvolvedores, como UTF-8 e UTF-16.

O principal objetivo do UNICODE é dar a todo símbolo um número, que o representará junto ao seu nome[1]. Esta iniciativa não só tem a ambição de englobar o maior números de idiomas possíveis, como também símbolos matemáticos e artísticos.

Inicialmente, a idéia era atribuir um código de até 2 bytes para os caracteres. Desta forma seria possível exibir 65536 caracteres[2]. Entretanto, hoje isto já não é mais verdade. Atualmente, ano de 2008, a versão 5.1.0 do padrão UNICODE contém mais de 100.000 caracteres[3], o que já ultrapassa os 2 bytes.

Um caracter é representado em UNICODE através da letra 'U' seguido pelo operador de adição e um código hexadecimal.

Exemplo:

	letra: m, código: U+006D

Então, escrever a palavra maçã fica da seguinte forma:

	U+006D U+0061 U+00E7 U+00E3

Entretanto, o computador só entende números, logo, deve-se achar uma forma de armazenar os códigos UNICODE na forma numérica. A primeira reação a se pensar é retirar o que não é número da sequência acima o que resultaria em:

	006D006100E700E3

Assim como para um ser humano, a sequencia numérica acima está ilegível para o computador, pois não é possível saber como tal sequência deve ser lida. Não há como saber que a sequência acima é UNICODE. Para contornar esse problema, foi inventado um conceito que se chama Byte Order Mark[4], que na verdade é uma sequência de bytes no começo da string que serve de identificação do conjunto de caracteres a ser usado pelo leitor de textos.

Isso pode ter alguns efeitos colaterais indesejados. Um exemplo é editar um arquivo PHP, onde seja usada a funçao header, no bloco de notas e salvá-lo no formato UTF-8. O seguinte warning será jogado:

Warning: Cannot modify header information - headers already sent by...

Sendo o Byte Order Mark uma estratégia ruim de informar o computador sobre o conjunto de caracteres utilizado, fica a cargo do desenvolvedor informar ao computador como os caracteres devem ser lidos e exibidos.

UTF-8

O UTF-8 surgiu como uma forma mais eficiente de codificar os símbolos UNICODE. Caracteres cujo código vão até 127 são codificados em um único byte e serão os mesmos da tabela ASCII [5]. Se o código do caracter no UNICODE for maior do que 127, serão necessários mais bytes para codificá-lo.

Diferente do Unicode, onde os caracteres são representados por 2 bytes, o caracter no UTF-8 tem um tamanho que pode variar de 1byte até 4 bytes [5].

É importante ressaltar que o UTF-8 não é um conjunto de caracteres. Segundo o documento que descreve o padrão [5]:

“A UTF-8 string is a sequence of octets representing a sequence of UCS characters.”


PHP e UTF-8

A principal relação entre PHP e UTF-8 é a de total incompatibilidade. Para as versões anteriores ao PHP6, todo caracter é representado somente por um byte. Não é possível fazer nenhuma manipulação segura de strings UTF-8 em PHP. Num arquivo UTF-8, o seguinte código ilustra a afirmação:

<?
	header('Content-Type: text/plain; charset=utf-8');
	print 'Saúde tem ' . strlen('Saúde') . ' letras';
?>

Dependendo da atividade, alguns problemas podem ser contornados com as funções utf8_encode e utf8_decode. Dependendo da situação, estas funções podem ser tornar inúteis. Basta tentar fazer uma manipulação de string no site GHL [6]. Strings UTF-8 são transformadas em ISO-8859-1 para que se possam fazer operações sobre Strings e retransformada em UTF-8 para exibição. Num arquivo no formato UTF-8, o seguinte código resume a ação citada:

<?
	header('Content-Type: text/plain; charset=utf-8');
	print utf8_encode( utf8_decode('Feijão') );
?>

O mesmo exemplo acima já não tem resultados aceitáveis quando feito assim:

<?
	header('Content-Type: text/plain; charset=utf-8');
	print utf8_encode( utf8_decode('الاتصالات'));
?>

Deve-se evitar fazer operações sobre strings que contenham mais de um byte quando estiver usando o PHP, pois um problema que ocorra durante um replace pode ser difícil de detectar.

Referências

[1] http://www.unicode.org/Public/UNIDATA/UnicodeData.txt

[2] http://www.joelonsoftware.com/articles/Unicode.html

[3] http://www.unicode.org/versions/Unicode5.1.0/

[4] http://en.wikipedia.org/wiki/Byte-order_mark

[5] http://www.ietf.org/rfc/rfc3629.txt

[6] http://www.globalhealthlibrary.net/php/index.php?lang=ar

Herramientas personales