2012-03-16 18 views
21

Potrzebuję sugestii na temat sposobu usunięcia BOM z pliku UTF-8 i utworzenia kopii reszty pliku xml.Jak usunąć BOM z pliku XML w Javie

+1

się downvotes nie są z powodu duplikatu, bo oni to pytanie jest zbyt szerokie w naturze - stackoverflow służy do pomocy w konkretnych, zlokalizowanych problemach programistycznych. Możemy pomóc Ci w debugowaniu programu, nie będziemy pisać dla ciebie. –

+0

Czekam na to, aby znaleźć się w punkcie -5 przed odpowiedzią;) – TacticalCoder

+0

@hari: jakie jest kodowanie twojego pliku? UTF-8? – TacticalCoder

Odpowiedz

32

Posiadanie narzędzia zrywającego z powodu BOM w pliku UTF-8 jest często spotykaną rzeczą w moim doświadczeniu. Nie wiem, dlaczego tak wiele downvotes (ale to daje mi szansę, aby spróbować uzyskać wystarczającą liczbę głosów, aby wygrać specjalny znaczek SO;)

Więcej poważnie: BOM UTF-8 zwykle nie robi tyle zmysłu ale jest w pełni poprawny (choć zniechęcony) przez specyfikacje. Problem polega na tym, że wiele osób nie zdaje sobie sprawy, że BOM jest poprawna w UTF-8 i dlatego napisał zepsute narzędzia/API, które nie przetwarzają poprawnie tych plików.

Teraz możesz mieć dwa różne problemy: możesz przetworzyć plik z Java lub musisz użyć Javy, aby programowo tworzyć/naprawiać pliki, których potrzebują inne (uszkodzone) narzędzia.

Miałem przypadek na jednym koncercie konsultacyjnym, w którym dział pomocy nadal otrzymywał wiadomości od użytkowników, którzy mieli problemy z edytorem tekstu, który zepsułby całkowicie poprawne pliki UTF-8 produkowane przez Javę. Musiałem więc obejść ten problem, upewniając się, że usunięto BOM z każdego pliku UTF-8, z którym mieliśmy do czynienia.

Chcę usunąć zestawienie komponentów z pliku, można utworzyć nowy plik i pominąć pierwsze trzy bajty. Na przykład:

... $ 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 ... 

Jak widać, plik zaczyna się od "ef bb bf", to jest (w pełni prawidłowy) UTF-8 BOM.

Oto metoda, która pobiera plik i tworzy kopię tego omijając pierwsze trzy bajty:

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

Należy pamiętać, że jest to „surowe”: Ci, że zwykle chcą najpierw upewnij się, że masz BOM przed wywołaniem tego lub "Złe myśli mogą się zdarzyć" [TM].

Możesz zajrzeć pliku potem:

... $ 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 ... 

I BOM nie ma ...

Teraz, jeśli po prostu chcesz usunąć przejrzysty BOM dla jednego uszkodzonego API Javy, a następnie może wykorzystać pushbackInputStream opisany tutaj: 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; } 

Zauważ, że to działa, ale powinien defin to naprawde poważniejszy problem, gdy inne narzędzia w łańcuchu prac mogą nie działać poprawnie z plikami UTF-8 mającymi LM.

A oto link do pytania o pełniejszą odpowiedź, obejmujących inne kodowanie, a także:

Byte order mark screws up file reading in Java

+0

Głosów nie są osądem * pytania * pytania, są osądem * jakości * pytania. Spójrz na podpowiedzi dla przycisków głosowania. – skaffman

+1

@skaffman: OK, ale zamiast downvotingu zapytałem, czy OP używa pliku UTF-8 (co podejrzewam, że ten problem jest zbyt powszechny), a następnie dodałem to do pytania (i edytowałem tagi). Nie wiem, co jeszcze można powiedzieć: * "Jak usunąć BOM z pliku?" * Jest dość oczywiste. Dodałem "UTF-8". Oczywiście łatwiej byłoby mi po prostu głosować;) – TacticalCoder

+0

@TacticalCoder bardzo dziękuję za sugestie ur .. Jestem pewien, że to rozwiązałoby pblm miałem. – hari