Detectando/descobrindo o charset/codificação de uma string – UTF-8, ISO-8859-1, etc.

Atenção! Essa postagem foi escrita há mais de 2 anos. Na informática tudo evolui muito rápido e algumas informações podem estar desatualizadas. Embora o conteúdo possa continuar relevante, lembre-se de levar em conta a data de publicação enquanto estiver lendo. Caso tenha sugestões para atualizá-la, não deixe de comentar!

Prefácio

Título longo (tem a ver com o Google? Magina!) mas tutorial bem simples. Recentemente enfrentei problemas com o UTF-8 (quem nunca enfrentou?) e testei vários modos de descobrir qual era a codificação usada, desde as gambiarras mais descaradas até as expressões regulares mais rebuscadas. Depois de muito bater a cabeça contra a mesa, cheguei a um resultado aceitável de como descobrir se a codificação da string era UTF-8 ou ISO-8859-1 utilizando strpos() e procurando pelo caractere à (uma vez que no português não existem palavras que comecei com “ã”), mas no fim das contas acabei percebendo que sempre tem alguém que envia uma mensagem totalmente em maiúsculo. Não vou simplesmente tacar um strtolower(). O jeito é pesquisar mais…

Conceito

Depois de muito dar socos na mesa e pesqusiar no meu amigo Google, chegou a hora do triste veredicto: caí em uma built-in function (funções que já vêm na linguagem). Nossa função se chama mb_detect_encoding() e, infelizmente, não irá funcionar a contento se não tiver um dedinho brasileiro ali.
A função só terá um resultado satisfatório se forem observados dos detalhes:

1. O segundo parâmetro da função (encoding list) deverá ser rigorosamente passado, contendo os dois encodes possíveis, a saber: UTF-8 e ISO-8859-1.
2. O último caractere da string não pode ser acentuado, para tanto utilizaremos um “método alternativo de eficácia momentânea” (vide Wikipédia: Gambiarra).

Mas e então, como fica? Vamos meter a mão na massa!

Mão na massa

Vamos montar uma funçãozinha bacana e bem simples, chamada codificacao() que irá retornar o charset de uma dada string. Talvez você perceba algo bizarro neste snippet, mas eu explico logo abaixo:

<?php
    function codificacao($string) {
        return mb_detect_encoding($string.'x', 'UTF-8, ISO-8859-1');
    }
?>

Agora você me pergunta: O que raios aquele “x” está fazendo ali?
A resposta é muito simples. Lembra que eu comentei que a string não pode terminar em caractere acentuado? (Hahahahahahahahahaha!)
Procura no manual do PHP que foi um um francês que sugeriu essa implementação (que mesmo após o PHP corrigir o bug, a função continuará funcionando do mesmo jeito) e eu gostei. :)

Conclusão

Nem sempre é possível resolver problemas sem um “ajustezinho brasileiro”. Resta-nos aguardar e ir atrás pra ver se um dia resolvem transpor este pequeno “detalhe” para o código-fonte do PHP! :P

Enviem críticas, dúvidas e sugestões, aproveitando que agora tem um formulário de contato meio enjambrado! xD

Um grande abraço a todos e fiquem com Deus!

  • Kuen

    Gostei do "x". Heheheh!!!

    Muito massa!!

    Flw!

  • Cara não consegui resolver o meu problema com esta abordagem, meu problema era ouuuuuutro na verdade, ehehe, mas essa função um dia com certeza vai ajudar, valeu!

  • Cara, parabéns, adorei o artigo, linguagem leve e eficiente, e resolveu um problema que a muito tempo eu precisava solucionar.

    Obrigado, e continue escrevendo.

    Abraços

  • >> Comentário #2

    >> Autor: Anselmo Battisti

    >> Em: 27/05/2008 às 17:07

    >> Cara não consegui resolver o meu problema com esta

    >> abordagem, meu problema era ouuuuuutro na verdade, ehehe,

    >> mas essa função um dia com certeza vai ajudar, valeu!

    OLHA AI HOJE ESSA FUNÇÃO ME AJUDOU, NÃO FALEI :) VALEU!

  • Interessante :)

  • FANTÁSTICO!!!

    Adorei a Gambiarra! re re re re

  • Huhauh. fiz um x um x um x no seu coração!!!

    muito bom, me salvou a vida!

    Parabéns pele tutorial.

  • muito bom o seu artigo estava a procura disso e solucionou meu problema.. grato…

  • muito boa essa dica estava a procura disso.. muito bom mesmo…

  • Guilherme

    Cara, ajudou esse baiano aqui. Muito obrigado!

  • Michel

    Tu acabou de ganhar o selo "Sou foda!". Parabéns.

  • Cara, muito bom esse Tuto aí me ajudo muito pro meu cliente de E-mail. vou recomendar muito. agora, "metodo alternativo de eficácia momentânea" é o melhor! ashuasausha

    • Rudolfo

      Tentem isto também:

      function has_utf8_encodingOrChars($str, $returnInForm__1forSpecialChars__2forEncoding__emptyForTrueOrFalse=0) {
      $s1=utf8_decode($str); $s2=utf8_decode($s1);
      preg_match('/?/',$s1,$m1); preg_match('/?/',$s2,$m2);
      if ( (strlen($s2) <= strlen($s1)) and (count($m1) < count($m2)) ) { //is UTF-8 AND is not in encoded format (instead shows accents/special chars)
      $o=1;}
      elseif ( (strlen($s2) < strlen($s1)) and (count($m1) == count($m2)) ) { //is UTF-8 AND IS in encoded format (doesn't show accents/special chars, but codes for each)
      $o=2;}
      if ($returnInForm__1forSpecialChars__2forEncoding__emptyForTrueOrFalse==0) {
      if (isset($o)) { return TRUE; } else { return FALSE; }}
      elseif ($returnInForm__1forSpecialChars__2forEncoding__emptyForTrueOrFalse==1 and $o==1) { return $s1; }
      elseif ($returnInForm__1forSpecialChars__2forEncoding__emptyForTrueOrFalse==1 and $o==2) { return $s2; }
      elseif ($returnInForm__1forSpecialChars__2forEncoding__emptyForTrueOrFalse==2 and $o==1) { return $str; }
      elseif ($returnInForm__1forSpecialChars__2forEncoding__emptyForTrueOrFalse==2 and $o==2) { return $s1; }
      else return $str;
      }
      Exemplos:
      "Quero saber se está na forma de UTF-8"
      has_utf8_encodingOrChars("café") retornará true
      has_utf8_encodingOrChars("café") retornará true
      has_utf8_encodingOrChars("carro") retornará false

      "Quero saber se está na forma de UTF-8 e, se estiver, retorne texto com caracteres especiais, não com códigos UTF-8"
      has_utf8_encodingOrChars("café",1) retornará "café"
      has_utf8_encodingOrChars("café",2) retornará "café"
      has_utf8_encodingOrChars("café",1) retornará "café"
      has_utf8_encodingOrChars("café",2) retornará "café"

      BOM PROVEITO!!! :) BomSaber@gmail.com:D

  • Pingback: PHP: Descobrindo o charset / codificação de uma string (ISO-8859, UTF-8) « rcdeveloper()

  • Bruno

    Puts nao deu certo para mim, mas a funçao do Rodolfo me parece que deu sim!!
    Valeu Rodolfo!!!

  • Wendel

    Muito boa mesmo. :)

  • Mt bom… ;D
    Descobri que por algum motivo fdp, mesmo todos meus arquivos estarem na codificação ANSI e o documento html setado com charset ISO-8859-1 no header do php, quando uso $.ajax os valores sao passados como UTF8…
    Que merda… preciso arrumar isso…

  • Deu certo! Obrigado por compartilhar isso com a gente, Rafael.

  • Whatyson Neves

    Excelente.

  • Rafael Mendes

    Muitoo bom!! ;D