Estou lendo muitos textos de vários feeds RSS e inserindo-os no meu banco de dados.
Obviamente, existem várias codificações de caracteres diferentes usadas nos feeds, por exemplo, UTF-8 e ISO 8859-1.
Infelizmente, às vezes há problemas com a codificação dos textos. Exemplo:
O "ß" em "Fußball" deve ficar assim no meu banco de dados: "Â". Se for um "Â", é exibido corretamente.
Às vezes, o "ß" em "Fußball" fica assim no meu banco de dados: "ÃÂ". Então é exibido incorretamente, é claro.
Em outros casos, o "ß" é salvo como um "ß" - portanto, sem nenhuma alteração. Então também é exibido incorretamente.
O que posso fazer para evitar os casos 2 e 3?
Como posso fazer tudo da mesma codificação, de preferência UTF-8? Quando devo usar utf8_encode()
, quando devo usar utf8_decode()
(está claro qual é o efeito, mas quando devo usar as funções?) E quando devo fazer nada com a entrada?
Como faço para tornar tudo a mesma codificação? Talvez com a função mb_detect_encoding()
? Posso escrever uma função para isso? Então, meus problemas são:
- Como descubro qual codificação o texto usa?
- Como o converto para UTF-8 - qualquer que seja a codificação antiga?
Uma função como esta funcionaria?
function correct_encoding($text) {
$current_encoding = mb_detect_encoding($text, 'auto');
$text = iconv($current_encoding, 'UTF-8', $text);
return $text;
}
Eu testei, mas não funciona. O que há de errado com isso?
Respostas:
Se você aplicar
utf8_encode()
a uma string já UTF-8, ela retornará uma saída UTF-8 ilegível.Eu criei uma função que aborda todos esses problemas. É chamado
Encoding::toUTF8()
.Você não precisa saber qual é a codificação de suas strings. Pode ser Latin1 ( ISO 8859-1) , Windows-1252 ou UTF-8, ou a cadeia pode ter uma mistura deles.
Encoding::toUTF8()
irá converter tudo para UTF-8.Fiz isso porque um serviço estava me fornecendo um feed de dados todo bagunçado, misturando UTF-8 e Latin1 na mesma string.
Uso:
Baixar:
https://github.com/neitanod/forceutf8
Incluí outra função,
Encoding::fixUFT8()
que corrigirá todas as seqüências UTF-8 que parecem ilegíveis.Uso:
Exemplos:
irá produzir:
Transformei a função (
forceUTF8
) em uma família de funções estáticas em uma classe chamadaEncoding
. A nova função éEncoding::toUTF8()
.fonte
Você primeiro precisa detectar qual codificação foi usada. Ao analisar feeds RSS (provavelmente via HTTP), você deve ler a codificação no
charset
parâmetro doContent-Type
campo do cabeçalho HTTP . Se não estiver presente, leia a codificação noencoding
atributo da instrução de processamento XML . Se isso também estiver faltando, use UTF-8 conforme definido na especificação .Editar Aqui está o que eu provavelmente faria:
Eu usaria cURL para enviar e buscar a resposta. Isso permite definir campos de cabeçalho específicos e buscar também o cabeçalho de resposta. Após buscar a resposta, você deve analisar a resposta HTTP e dividi-la em cabeçalho e corpo. O cabeçalho deve conter o
Content-Type
campo de cabeçalho que contém o tipo MIME e (espero) ocharset
parâmetro com a codificação / conjunto de caracteres também. Caso contrário, analisaremos o XML PI quanto à presença doencoding
atributo e obteremos a codificação a partir daí. Se isso também estiver faltando, as especificações XML definem o uso de UTF-8 como codificação.fonte
charset=
eencoding=
e não apenas nas posições apropriadas. E terceiro, você não está verificando se a codificação declarada é aceita.Detectar a codificação é difícil.
mb_detect_encoding
funciona adivinhando, com base em vários candidatos aprovados. Em algumas codificações, determinadas seqüências de bytes são inválidas e, portanto, podem distinguir entre vários candidatos. Infelizmente, existem muitas codificações em que os mesmos bytes são válidos (mas diferentes). Nesses casos, não há como determinar a codificação; Você pode implementar sua própria lógica para fazer suposições nesses casos. Por exemplo, é provável que os dados provenientes de um site japonês tenham uma codificação japonesa.Contanto que você só lidar com idiomas da Europa Ocidental, as três principais codificações a considerar são
utf-8
,iso-8859-1
ecp-1252
. Como esses padrões são padrão para muitas plataformas, eles também são os mais propensos a serem relatados incorretamente. Por exemplo. se as pessoas usam codificações diferentes, é provável que sejam francas a respeito, pois caso contrário, seu software quebraria com muita frequência. Portanto, uma boa estratégia é confiar no provedor, a menos que a codificação seja relatada como uma dessas três. Você ainda deve verificar duas vezes se é realmente válido, usandomb_check_encoding
(observe que válido não é o mesmo que ser - a mesma entrada pode ser válida para muitas codificações). Se for um desses, você poderá usarmb_detect_encoding
para distinguir entre eles. Felizmente isso é bastante determinístico; Você só precisa usar a sequência de detecção adequada, que éUTF-8,ISO-8859-1,WINDOWS-1252
.Depois de detectar a codificação, você precisa convertê-la em sua representação interna (
UTF-8
é a única opção sensata). A função éutf8_encode
transformadaISO-8859-1
emUTF-8
, portanto, pode ser usada apenas para esse tipo de entrada específico. Para outras codificações, usemb_convert_encoding
.fonte
Uma maneira muito boa de implementar uma
isUTF8
função-pode ser encontrada em php.net :fonte
mb_check_encoding($string, 'UTF-8')
Esta folha de dicas lista algumas advertências comuns relacionadas ao manuseio de UTF-8 no PHP: http://developer.loftdigital.com/blog/php-utf-8-cheatsheet
Essa função de detecção de caracteres multibyte em uma string também pode ser útil ( fonte ):
fonte
Um pouco de atenção. Você disse que o "ß" deve ser exibido como "Â" no seu banco de dados.
Provavelmente porque você está usando um banco de dados com codificação de caracteres Latin-1 ou, possivelmente, sua conexão PHP-MySQL está incorreta, isto é, P acredita que seu MySQL está configurado para usar UTF-8, para que ele envie dados como UTF-8 , mas seu MySQL acredita que o PHP está enviando dados codificados como ISO 8859-1, portanto, mais uma vez, você pode tentar codificar seus dados enviados como UTF-8, causando esse tipo de problema.
Dê uma olhada no mysql_set_charset . Isso pode ajudá-lo.
fonte
Sua codificação parece que você codificou em UTF-8 duas vezes ; isto é, de alguma outra codificação, em UTF-8 e novamente em UTF-8. Como se você tivesse ISO 8859-1, convertido de ISO 8859-1 para UTF-8 e tratado a nova string como ISO 8859-1 para outra conversão em UTF-8.
Aqui estão alguns pseudocódigo do que você fez:
Você deveria tentar:
mb_detect_encoding()
ou o que você quiser usarIsso pressupõe que, na conversão "intermediária", você utilizou a ISO 8859-1. Se você usou o Windows 1252, converta-o para o Windows 1252 (latin1). A codificação original da fonte não é importante; o que você usou em falha, segunda conversão é.
Este é o meu palpite sobre o que aconteceu; há muito pouco que você poderia ter feito para obter quatro bytes no lugar de um byte ASCII estendido.
O idioma alemão também usa ISO 8859-2 e Windows-1250 (latino-2).
fonte
O interessante
mb_detect_encoding
emb_convert_encoding
é que a ordem das codificações sugeridas é importante:Portanto, convém usar uma ordem específica ao especificar as codificações esperadas. Ainda assim, lembre-se de que isso não é infalível.
fonte
if ($input_is_not_UTF8) $input_is_windows1252 = true;
. Veja também: html.spec.whatwg.org/multipage/…Você precisa testar o conjunto de caracteres na entrada, pois as respostas podem vir codificadas com codificações diferentes.
Forço todo o conteúdo a ser enviado ao UTF-8, fazendo a detecção e a tradução usando a seguinte função:
Essa rotina transformará todas as variáveis PHP que vêm do host remoto em UTF-8.
Ou ignore o valor se a codificação não puder ser detectada ou convertida.
Você pode personalizá-lo de acordo com suas necessidades.
Apenas invoque-o antes de usar as variáveis.
fonte
Trabalhar com a codificação de caracteres dos feeds RSS parece ser complicado . Mesmo páginas da Web normais geralmente omitem ou mentem sobre sua codificação.
Portanto, você pode tentar usar a maneira correta de detectar a codificação e voltar a alguma forma de detecção automática (suposição).
fonte
charset
/encoding
declaração se por: descrever a codificação dos dados é codificado em.Sei que essa é uma pergunta mais antiga, mas acho que uma resposta útil nunca é demais. Eu estava tendo problemas com minha codificação entre um aplicativo de desktop, SQLite e variáveis GET / POST. Alguns estariam em UTF-8, outros em ASCII, e basicamente tudo estragaria quando personagens estrangeiros se envolvessem.
Aqui está a minha solução. Ele limpa seu GET / POST / REQUEST (eu omiti os cookies, mas você pode adicioná-los, se desejar) em cada carregamento da página antes do processamento. Funciona bem em um cabeçalho. O PHP lançará avisos se não puder detectar a codificação de origem automaticamente, portanto, esses avisos serão suprimidos com @ 's.
fonte
Eu estava procurando soluções para codificação desde idades , e esta página é provavelmente a conclusão de anos de pesquisa! Testei algumas das sugestões que você mencionou e aqui estão minhas anotações:
Esta é a minha string de teste:
Eu faço um INSERT para salvar essa sequência em um banco de dados em um campo definido como
utf8_general_ci
O conjunto de caracteres da minha página é UTF-8.
Se eu fizer um INSERT assim, no meu banco de dados, tenho alguns personagens provavelmente vindos de Marte ...
Então, eu preciso convertê-los em algum UTF-8 "saudável". Eu tentei
utf8_encode()
, mas os caracteres alienígenas ainda estavam invadindo meu banco de dados ...Então, tentei usar a função
forceUTF8
postada no número 8, mas no banco de dados a string salva é assim:Então, coletando mais algumas informações nesta página e mesclando-as com outras informações em outras páginas, resolvi meu problema com esta solução:
Agora, no meu banco de dados, tenho minha string com a codificação correta.
NOTA: Somente observe para cuidar está em funcionamento
mysql_client_encoding
! Você precisa estar conectado ao banco de dados, porque esta função deseja um ID de recurso como parâmetro.Mas bem, eu apenas faço essa recodificação antes do meu INSERT, portanto, para mim, não é um problema.
fonte
UTF-8
codificação do cliente para mysql? Não precisaria de conversão manual dessa maneiraÉ simples: quando você obtém algo que não é UTF-8, deve codificá- lo para UTF-8.
Portanto, quando você está buscando um determinado feed que seja ISO 8859-1, analise-o
utf8_encode
.No entanto, se você está buscando um feed UTF-8, não precisa fazer nada.
fonte
php.net/
mb_detect_encoding
ou
Realmente não sei quais são os resultados, mas sugiro que você pegue alguns de seus feeds com codificações diferentes e tente se
mb_detect_encoding
funciona ou não.update
auto é a abreviação de "ASCII, JIS, UTF-8, EUC-JP, SJIS". retorna o conjunto de caracteres detectado, que você pode usar para converter a string em utf-8 com iconv .
Eu não testei, então não há garantia. e talvez haja uma maneira mais simples.
fonte
@harpax que funcionou para mim. No meu caso, isso é bom o suficiente:
fonte
Depois de ordenar seus scripts php, não esqueça de dizer ao mysql qual charset você está passando e gostaria de receber.
Exemplo: definir conjunto de caracteres utf8
A passagem de dados utf8 para uma tabela latin1 em uma sessão de E / S latin1 fornece esses pés de pássaro desagradáveis. Vejo isso todos os dias nas lojas de comércio eletrônico. Voltar e quarta, pode parecer certo. Mas o phpmyadmin mostrará a verdade. Ao dizer ao mysql que conjunto de caracteres você está passando, ele manipulará a conversão de dados mysql para você.
Como recuperar dados mysql embaralhados existentes é outro tópico a ser discutido. :)
fonte
Esta versão é para o idioma alemão, mas você pode modificar os $ CHARSETS e os $ TESTCHARS
fonte
Obtenha codificação de cabeçalhos e converta-a em utf-8.
fonte
Ÿ
é Mojibake paraß
. No seu banco de dados, você pode ter hexadecimalVocê não deve usar nenhuma função de codificação / decodificação no PHP; em vez disso, você deve configurar o banco de dados e a conexão a ele corretamente.
Se o MySQL estiver envolvido, consulte: Problemas com caracteres utf8; o que vejo não é o que guardei
fonte
Encontre a solução aqui http://deer.org.ua/2009/10/06/1/
Eu acho que @ é uma má decisão e faço algumas alterações na solução do deer.org.ua;
fonte
A resposta mais votada não funciona. Aqui está o meu e espero que ajude.
fonte
Quando você tenta lidar com vários idiomas, como japonês e coreano, pode ter problemas. mb_convert_encoding com o parâmetro 'auto' não funciona bem. Definir mb_detect_order ('ASCII, UTF-8, JIS, EUC-JP, SJIS, EUC-KR, UHC') não ajuda, pois detecta EUC- * incorretamente.
Concluí que, desde que as strings de entrada venham do HTML, ele deve usar 'charset' em um meta elemento. Eu uso o Simple HTML DOM Parser porque ele suporta HTML inválido.
O trecho abaixo extrai o elemento de título de uma página da web. Se você deseja converter uma página inteira, remova algumas linhas.
fonte
Eu tive o mesmo problema com o phpQuery ( ISO-8859-1 em vez de UTF-8 ) e esse truque me ajudou:
mb_internal_encoding('UTF-8')
,phpQuery::newDocumentHTML($html, 'utf-8')
,mbstring.internal_encoding
E outras manipulações não tomou qualquer efeito.fonte
Experimente sem 'auto'
Isso é:
ao invés de:
Mais informações podem ser encontradas aqui: mb_detect_encoding
fonte