Leitura UTF-8 – Marcador BOM

Eu estou lendo um arquivo através de um FileReader – o arquivo é decodificado pelo UTF-8 (com BOM) agora meu problema é: Eu li o arquivo e imprimi uma string, mas infelizmente o marcador BOM também é gerado. Por que isso ocorre?

fr = new FileReader(file); br = new BufferedReader(fr); String tmp = null; while ((tmp = br.readLine()) != null) { String text; text = new String(tmp.getBytes(), "UTF-8"); content += text + System.getProperty("line.separator"); } 

saída após a primeira linha

 ? 

Em Java, você precisa consumir manualmente a BOM UTF8, se presente. Esse comportamento está documentado no database de bugs do Java, aqui e aqui . Não haverá correção para agora, pois isso quebrará as ferramentas existentes, como analisadores JavaDoc ou XML. O Apache IO Commons fornece um BOMInputStream para lidar com essa situação.

Dê uma olhada nesta solução: Lidar com arquivo UTF8 com BOM

A correção mais fácil é provavelmente apenas remover o \uFEFF resultante da string, já que é extremamente improvável que apareça por qualquer outro motivo.

 tmp = tmp.replace("\uFEFF", ""); 

Veja também este relatório de bug do Guava

Use a biblioteca do Apache Commons .

Classe: org.apache.commons.io.input.BOMInputStream

Exemplo de uso:

 String defaultEncoding = "UTF-8"; InputStream inputStream = new FileInputStream(someFileWithPossibleUtf8Bom); try { BOMInputStream bOMInputStream = new BOMInputStream(inputStream); ByteOrderMark bom = bOMInputStream.getBOM(); String charsetName = bom == null ? defaultEncoding : bom.getCharsetName(); InputStreamReader reader = new InputStreamReader(new BufferedInputStream(bOMInputStream), charsetName); //use reader } finally { inputStream.close(); } 

Aqui está como eu uso o Apache BOMInputStream, ele usa um bloco try-with-resources. O argumento “false” diz ao object para ignorar os seguintes BOMs (usamos arquivos de texto “BOM-less” por motivos de segurança, haha):

 try( BufferedReader br = new BufferedReader( new InputStreamReader( new BOMInputStream( new FileInputStream( file), false, ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_32BE, ByteOrderMark.UTF_32LE ) ) ) ) { // use br here } catch( Exception e) } 

É mencionado aqui que isso geralmente é um problema com arquivos no Windows.

Uma solução possível seria executar o arquivo por meio de uma ferramenta como dos2unix primeiro.

Use o Apache Commons IO .

Por exemplo, vamos dar uma olhada no meu código (usado para ler um arquivo de texto com caracteres latinos e cirílicos) abaixo:

 String defaultEncoding = "UTF-16"; InputStream inputStream = new FileInputStream(new File("/temp/1.txt")); BOMInputStream bomInputStream = new BOMInputStream(inputStream); ByteOrderMark bom = bomInputStream.getBOM(); String charsetName = bom == null ? defaultEncoding : bom.getCharsetName(); InputStreamReader reader = new InputStreamReader(new BufferedInputStream(bomInputStream), charsetName); int data = reader.read(); while (data != -1) { char theChar = (char) data; data = reader.read(); ari.add(Character.toString(theChar)); } reader.close(); 

Como resultado, temos um ArrayList chamado “ari” com todos os caracteres do arquivo “1.txt”, com exceção do BOM.

Considere o UnicodeReader do Google, que faz todo esse trabalho para você.

 Charset utf8 = Charset.forName("UTF-8"); // default if no BOM present try (Reader r = new UnicodeReader(new FileInputStream(file), utf8)) { .... } 

Dependência Maven:

  com.google.gdata core 1.47.1  

A maneira mais fácil que encontrei de ignorar o BOM

 BufferedReader br = new BufferedReader(new InputStreamReader(fis)); while ((currentLine = br.readLine()) != null) { //case of, remove the BOM of UTF-8 BOM currentLine = currentLine.replace("","");