Estou tentando ler arquivos CSV usando Java. Alguns dos arquivos podem ter uma marca de ordem de bytes no início, mas não todos. Quando presente, a ordem de bytes é lida junto com o resto da primeira linha, causando problemas com comparações de strings.
Existe uma maneira fácil de pular a marca de ordem de byte quando ela está presente?
Obrigado!
Respostas:
EDIT : Eu fiz um lançamento adequado no GitHub: https://github.com/gpakosz/UnicodeBOMInputStream
Aqui está uma classe que codifiquei há um tempo, acabei de editar o nome do pacote antes de colar. Nada de especial, é bastante semelhante às soluções postadas no banco de dados de bugs do SUN. Incorpore-o em seu código e está tudo bem.
E você está usando desta forma:
fonte
A biblioteca Apache Commons IO tem um
InputStream
que pode detectar e descartar BOMs:BOMInputStream
(javadoc) :Se você também precisa detectar codificações diferentes, ele também pode distinguir entre várias marcas de ordem de byte diferentes, por exemplo, UTF-8 vs. UTF-16 big + little endian - detalhes no link doc acima. Você pode então usar o detectado
ByteOrderMark
para escolher umCharset
para decodificar o fluxo. (Provavelmente existe uma maneira mais simplificada de fazer isso se você precisar de toda essa funcionalidade - talvez o UnicodeReader na resposta de BalusC?). Observe que, em geral, não há uma maneira muito boa de detectar em qual codificação alguns bytes estão, mas se o fluxo começar com um BOM, aparentemente isso pode ser útil.Editar : se você precisa detectar o BOM em UTF-16, UTF-32, etc, o construtor deve ser:
Comentário de Upvote @ martin-charlesworth :)
fonte
boolean
argumento para especificar se devo incluir ou excluir o BOM. Exemplo:BOMInputStream bomIn = new BOMInputStream(in, false); // don't include the BOM
BOMInputStream bomIn = new BOMInputStream(is, ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_32BE, ByteOrderMark.UTF_32LE);
BOMInputStream(InputStream delegate) Constructs a new BOM InputStream that excludes a ByteOrderMark.UTF_8 BOM.
Solução mais simples:
Amostra de uso:
Funciona com todas as 5 codificações UTF!
fonte
A API de dados do Google possui um dispositivo
UnicodeReader
que detecta automaticamente a codificação.Você pode usá-lo em vez de
InputStreamReader
. Aqui está um extrato levemente compactado de sua fonte que é bastante simples:fonte
(bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)
ser verdadeiro, então o caso UTF-16LE ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)
) já teria correspondido.O BOMInputStream
Apache Commons IO
da Biblioteca já foi mencionado por @rescdsk, mas não vi menção de como obter um sem o BOM.InputStream
Veja como fiz no Scala.
fonte
public BOMInputStream(InputStream delegate) { this(delegate, false, ByteOrderMark.UTF_8); }
. ExcluiUTF-8 BOM
por padrão.Constructs a new BOM InputStream that excludes a ByteOrderMark.UTF_8 BOM.
Para simplesmente remover os caracteres BOM do seu arquivo, recomendo usar o Apache Common IO
Defina incluir como falso e seus caracteres BOM serão excluídos.
fonte
Infelizmente, não. Você terá que se identificar e pular. Esta página detalha o que você deve observar. Veja também esta pergunta do SO para mais detalhes.
fonte
Tive o mesmo problema e, como não estava lendo um monte de arquivos, fiz uma solução mais simples. Acho que minha codificação era UTF-8 porque quando imprimi o caractere ofensivo com a ajuda desta página: Obtenha o valor unicode de um caractere , descobri que era
\ufeff
. Usei o códigoSystem.out.println( "\\u" + Integer.toHexString(str.charAt(0) | 0x10000).substring(1) );
para imprimir o valor Unicode ofensivo.Assim que obtive o valor Unicode ofensivo, substituí-o na primeira linha do meu arquivo antes de continuar lendo. A lógica de negócios dessa seção:
Isso resolveu meu problema. Então, consegui processar o arquivo sem nenhum problema. Eu adicionei
trim()
apenas no caso de espaço em branco à esquerda ou à direita, você pode fazer isso ou não, com base em quais são suas necessidades específicas.fonte