Com referência ao seguinte encadeamento: Java App: Não foi possível ler o arquivo codificado iso-8859-1 corretamente
Qual é a melhor maneira de determinar programaticamente a codificação correta do conjunto de caracteres de um fluxo de entrada / arquivo?
Eu tentei usar o seguinte:
File in = new File(args[0]);
InputStreamReader r = new InputStreamReader(new FileInputStream(in));
System.out.println(r.getEncoding());
Mas em um arquivo que eu sei que está codificado com ISO8859_1, o código acima gera ASCII, que não está correto, e não me permite renderizar corretamente o conteúdo do arquivo de volta ao console.
Reader.getEncoding
retorna a codificação que o leitor foi configurado para usar, que no seu caso é a codificação padrão.Respostas:
Eu usei esta biblioteca, semelhante ao jchardet, para detectar a codificação em Java: http://code.google.com/p/juniversalchardet/
fonte
Você não pode determinar a codificação de um fluxo de bytes arbitrário. Essa é a natureza das codificações. Uma codificação significa um mapeamento entre um valor de byte e sua representação. Portanto, toda codificação "poderia" estar certa.
O método getEncoding () retornará a codificação configurada (leia o JavaDoc ) para o fluxo. Não vai adivinhar a codificação para você.
Alguns fluxos informam qual codificação foi usada para criá-los: XML, HTML. Mas não um fluxo de bytes arbitrário.
De qualquer forma, você pode tentar adivinhar uma codificação por conta própria, se for necessário. Todo idioma tem uma frequência comum para cada caractere. Em inglês, o caractere aparece com muita frequência, mas ê aparece muito raramente. Em um fluxo ISO-8859-1, geralmente não há caracteres 0x00. Mas um fluxo UTF-16 tem muitos deles.
Ou: você pode perguntar ao usuário. Já vi aplicativos que apresentam um trecho do arquivo em diferentes codificações e solicitam que você selecione o "correto".
fonte
verifique isto: http://site.icu-project.org/ (icu4j) eles têm bibliotecas para detectar charset a partir do IOStream poderia ser simples assim:
fonte
Aqui estão os meus favoritos:
TikaEncodingDetector
Dependência:
Amostra:
GuessEncoding
Dependência:
Amostra:
fonte
CharsetDectector
.Certamente, você pode validar o arquivo para um conjunto de caracteres específico decodificando -o com um
CharsetDecoder
e observando os erros de "entrada malformada" ou "caractere não mappável". Obviamente, isso apenas informa se um conjunto de caracteres está errado; não diz se está correto. Para isso, você precisa de uma base de comparação para avaliar os resultados decodificados, por exemplo, você sabe de antemão se os caracteres estão restritos a algum subconjunto ou se o texto segue algum formato estrito? A linha inferior é que a detecção de charset é uma adivinhação sem garantias.fonte
Qual biblioteca usar?
No momento da redação deste artigo, são três as bibliotecas que emergem:
Não incluo Apache Any23 porque ele usa o ICU4j 3.4 sob o capô.
Como saber qual deles detectou o direito caracteres (ou o mais próximo possível)?
É impossível certificar o conjunto de caracteres detectado por cada uma das bibliotecas acima. No entanto, é possível perguntar por vez e pontuar a resposta retornada.
Como pontuar a resposta retornada?
Cada resposta pode ser atribuída a um ponto. Quanto mais pontos uma resposta tiver, mais confiança terá o conjunto de caracteres detectado. Este é um método simples de pontuação. Você pode elaborar outros.
Existe algum código de exemplo?
Aqui está um trecho completo implementando a estratégia descrita nas linhas anteriores.
Melhorias: O
guessEncoding
método lê o fluxo de entrada completamente. Para fluxos de entrada grandes, isso pode ser uma preocupação. Todas essas bibliotecas liam todo o fluxo de entrada. Isso implicaria um grande consumo de tempo para detectar o conjunto de caracteres.É possível limitar o carregamento inicial de dados a alguns bytes e executar a detecção do conjunto de caracteres apenas nesses poucos bytes.
fonte
As bibliotecas acima são simples detectores de lista técnica que, obviamente, só funcionam se houver uma lista técnica no início do arquivo. Dê uma olhada em http://jchardet.sourceforge.net/, que digitaliza o texto
fonte
Até onde eu sei, não existe uma biblioteca geral nesse contexto que seja adequada para todos os tipos de problemas. Portanto, para cada problema, você deve testar as bibliotecas existentes e selecionar a melhor que satisfaça as restrições do seu problema, mas geralmente nenhuma delas é apropriada. Nestes casos, você pode escrever seu próprio detector de codificação! Como eu escrevi ...
Eu escrevi uma ferramenta de meta java para detectar a codificação charset de páginas da Web em HTML, usando o IBM ICU4j e o Mozilla JCharDet como componentes internos. Aqui você encontra minha ferramenta, por favor leia a seção README antes de qualquer outra coisa. Além disso, você pode encontrar alguns conceitos básicos desse problema no meu artigo e em suas referências.
Abaixo, fiz alguns comentários úteis que experimentei em meu trabalho:
fonte
Encontrei uma boa biblioteca de terceiros que pode detectar a codificação real: http://glaforge.free.fr/wiki/index.php?wiki=GuessEncoding
Não testei extensivamente, mas parece funcionar.
fonte
Se você usa o ICU4J ( http://icu-project.org/apiref/icu4j/ )
Aqui está o meu código:
Lembre-se de colocar todo o try-catch necessário.
Espero que isso funcione pra você.
fonte
Se você não conhece a codificação dos seus dados, não é tão fácil determinar, mas você pode tentar usar uma biblioteca para adivinhar . Além disso, há uma pergunta semelhante .
fonte
Para arquivos ISO8859_1, não há uma maneira fácil de diferenciá-los do ASCII. Para arquivos Unicode, no entanto, geralmente é possível detectar isso com base nos primeiros bytes do arquivo.
Os arquivos UTF-8 e UTF-16 incluem uma BOM ( Byte Order Mark ) no início do arquivo. A lista técnica é um espaço sem quebra de largura zero.
Infelizmente, por razões históricas, o Java não detecta isso automaticamente. Programas como o Bloco de notas verificarão a lista técnica e usarão a codificação apropriada. Usando unix ou Cygwin, você pode verificar a lista técnica com o comando file. Por exemplo:
Para Java, sugiro que você verifique este código, que irá detectar os formatos de arquivo comuns e selecionar a codificação correta: Como ler um arquivo e especificar automaticamente a codificação correta
fonte
Uma alternativa ao TikaEncodingDetector é usar o Tika AutoDetectReader .
fonte
Em Java simples:
Essa abordagem tentará as codificações uma a uma até que uma funcione ou que as esgotemos. (BTW, minha lista de codificações possui apenas esses itens porque são as implementações de conjuntos de caracteres necessárias em todas as plataformas Java, https://docs.oracle.com/javase/9/docs/api/java/nio/charset/Charset.html )
fonte
Você pode escolher o conjunto de caracteres apropriado no Construtor :
fonte