Lettura UTF-8 – indicatore BOM

Sto leggendo un file attraverso un FileReader – il file è decodificato UTF-8 (con BOM) ora il mio problema è: leggo il file e metto in output una stringa, ma purtroppo anche il marcatore BOM viene emesso. Perché questo si verifica?

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"); } 

uscita dopo la prima riga

 ? 

In Java, devi consumare manualmente la BOM UTF8 se presente. Questo comportamento è documentato nel database dei bug Java, qui e qui . Non ci sarà alcuna correzione per ora perché interromperà strumenti esistenti come i parser JavaDoc o XML. Apache IO Commons fornisce un BOMInputStream per gestire questa situazione.

Dai un’occhiata a questa soluzione: Gestisci il file UTF8 con BOM

La soluzione più semplice è probabilmente solo per rimuovere il \uFEFF risultante dalla stringa, poiché è estremamente improbabile che venga visualizzato per qualsiasi altro motivo.

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

Vedi anche questo bug report Guava

Usa la libreria di Apache Commons .

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

Esempio di utilizzo:

 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(); } 

Ecco come utilizzo Apache BOMInputStream, utilizza un blocco try-with-resources. L’argomento “false” dice all’object di ignorare le seguenti BOM (usiamo file di testo “senza BOM” per motivi di sicurezza, 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) } 

Qui viene menzionato che questo è solitamente un problema con i file su Windows.

Una ansible soluzione sarebbe eseguire il file attraverso uno strumento come dos2unix prima.

Usa Apache Commons IO .

Per esempio, diamo un’occhiata al mio codice (usato per leggere un file di testo con caratteri latini e cirillici) di seguito:

 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(); 

Di conseguenza abbiamo un ArrayList chiamato “ari” con tutti i caratteri del file “1.txt” ad eccezione di BOM.

Considera UnicodeReader di Google che fa tutto questo per te.

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

Dipendenza da Maven:

  com.google.gdata core 1.47.1  

Il modo più semplice che ho trovato per bypassare 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("","");