2012-03-16 7 views
21

Ho bisogno di suggerimenti sul modo di rimuovere BOM da un file UTF-8 e di creare una copia del resto del file xml.Come rimuovere BOM da un file XML in Java

+1

i downvotes non sono a causa di un duplicato, che stanno perché questa domanda è troppo ampia in natura - StackOverflow serve per aiutare con problemi di programmazione specifici e localizzati. Possiamo aiutarti a eseguire il debug di un programma, non ne scriveremo uno per te. –

+0

Sto aspettando che questo arrivi a -5 prima di rispondere;) – TacticalCoder

+0

@hari: qual è la codifica del tuo file? UTF-8? – TacticalCoder

risposta

32

Avere uno strumento che si rompe a causa di una distinta base in un file UTF-8 è una cosa molto comune nella mia esperienza . Non so perché ci siano così tanti downvotes (ma poi mi dà la possibilità di provare a ottenere abbastanza voti per vincere un badge SO speciale;)

Più seriamente: un BOM UTF-8 in genere non rende questo ha molto senso ma è pienamente valido (anche se scoraggiato) dalle specifiche. Ora il problema è che molte persone non sono consapevoli del fatto che un BOM è valido in UTF-8 e quindi ha scritto strumenti/API non funzionanti che non elaborano correttamente questi file.

Ora è possibile che si verifichino due problemi diversi: è possibile elaborare il file da Java oppure è necessario utilizzare Java per creare/correggere a livello di codice gli altri strumenti necessari.

Ho avuto il caso in un concerto di consulenza in cui l'helpdesk continuava a ricevere messaggi da utenti che avevano problemi con un editor di testo che avrebbe rovinato file UTF-8 perfettamente validi prodotti da Java. Quindi ho dovuto aggirare quel problema assicurandomi di rimuovere il BOM da ogni singolo file UTF-8 con cui ci stavamo confrontando.

Se si desidera eliminare un DB da un file, è possibile creare un nuovo file e saltare i primi tre byte. Per esempio:

... $ file /tmp/src.txt 
/tmp/src.txt: UTF-8 Unicode (with BOM) English text 

... $ ls -l /tmp/src.txt 
-rw-rw-r-- 1 tact tact 1733 2012-03-16 14:29 /tmp/src.txt 

... $ hexdump -C /tmp/src.txt | head -n 1 
00000000 ef bb bf 50 6f 6b 65 ... 

Come si può vedere, il file inizia con "ef bb bf", questo è il (pienamente valida) UTF-8 BOM.

Ecco un metodo che prende un file e fa una copia di esso saltando i primi tre byte:

public static void workAroundbrokenToolsAndAPIs(File sourceFile, File destFile) throws IOException { 
    if(!destFile.exists()) { 
     destFile.createNewFile(); 
    } 

    FileChannel source = null; 
    FileChannel destination = null; 

    try { 
     source = new FileInputStream(sourceFile).getChannel(); 
     source.position(3); 
     destination = new FileOutputStream(destFile).getChannel(); 
     destination.transferFrom(source, 0, source.size() - 3); 
    } 
    finally { 
     if(source != null) { 
      source.close(); 
     } 
     if(destination != null) { 
      destination.close(); 
     } 
    } 
} 

Si noti che si tratta di "raw": si dovrebbe menzionare vuole prima assicurarsi di avere un BOM prima di chiamare questo o "Bad Thinks May Happen" [TM].

Potete guardare il file in seguito:

... $ file /tmp/dst.txt 
/tmp/dst.txt: UTF-8 Unicode English text 

... $ ls -l /tmp/dst.txt 
-rw-rw-r-- 1 tact tact 1730 2012-03-16 14:41 /tmp/dst.txt 

... $ hexdump -C /tmp/dst.txt 
00000000 50 6f 6b 65 ... 

E il BOM è andato ...

Ora, se si vuole semplicemente rimuovere in modo trasparente la distinta per una vostra API Java rotto, allora si potrebbe utilizzare il PushbackInputStream descritto qui: why org.apache.xerces.parsers.SAXParser does not skip BOM in utf8 encoded xml?

private static InputStream checkForUtf8BOMAndDiscardIfAny(InputStream inputStream) throws IOException { 
    PushbackInputStream pushbackInputStream = new PushbackInputStream(new BufferedInputStream(inputStream), 3); 
    byte[] bom = new byte[3]; 
    if (pushbackInputStream.read(bom) != -1) { 
     if (!(bom[0] == (byte) 0xEF && bom[1] == (byte) 0xBB && bom[2] == (byte) 0xBF)) { 
      pushbackInputStream.unread(bom); 
     } 
    } 
    return pushbackInputStream; } 

Nota che questo funziona, ma deve defin itely NON risolvere il problema più grave in cui è possibile avere altri strumenti nella catena di lavoro che non funzionano correttamente con i file UTF-8 con una distinta componenti.

Ed ecco un link ad una domanda con una risposta più completa, che copre altre codifiche così:

Byte order mark screws up file reading in Java

+0

voti non sono un giudizio sul * soggetto * di una domanda, sono un giudizio sulla * qualità * di una domanda. Guarda i tooltip per i pulsanti di voto. – skaffman

+1

@skaffman: OK ma invece di downvoting ho chiesto se OP stava usando un file UTF-8 (che sospettavo per quel problema è fin troppo comune) e poi l'ho aggiunto alla domanda (e modificato i tag). Non so cos'altro si può dire: * "Come rimuovere una BOM da un file?" * È piuttosto auto-esplicativo. Ho aggiunto "UTF-8". Certamente sarebbe stato più facile per me fare semplicemente un downvote;) – TacticalCoder

+0

@TacticalCoder ringrazia molto per i tuoi suggerimenti .. Sono sicuro che questo avrebbe risolto il problema che avevo. – hari