2011-03-18 19 views
5

utf8 kodlama ile bir xml var. Ve bu dosya BOM dosyasının başlangıcını içerir. Ayrıştırma sırasında org.xml.sax.SAXParseException ile karşılaşıyorum: Prolog'da içeriğe izin verilmiyor. Dosyaları 3 bayttan çıkaramıyorum. Dosyayı belleğe yükleyemiyorum ve buradan kaldırabilirsiniz (dosyalar büyük). Performans nedeniyle, SAX ayrıştırıcısı kullanıyorum ve "" etiketinden önce mevcutsa 3 baytı atlamak istiyorum. Bunun için InputStreamReader mi kullanmalıyım?neden org.apache.xerces.parsers.SAXParser, utf8 kodlanmış xml'de BOM'yi atlamıyor?

Java'da yeni - lütfen bana doğru yolu göster.

+0

[Bayt sırası işareti vidalarının olası yinelenen kadar dosya okuma Java] (http://stackoverflow.com/questions/1835430/byte-order-mark-screws-up-file-reading-in-java) –

cevap

4

Bu daha önce geldi ve bana geldiğinde Yığın Taşması konusunda the answer buldum. Bağlantılı cevap, BOM'yi test etmek için PushbackInputStream kullanır.

1

Aynı sorun yaşadıysanız ve bu kodla çözdük:

private static InputStream checkForUtf8BOM(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; 
} 
+0

Bu UTF8 için ... UTF16'nın farklı olacağını varsayalım onun sadece 2 bayt)? – Trinition

+0

Geç için üzgünüz. Evet, UTF16, yalnızca iki baytlık bir BOM'a sahiptir: 0xFE 0xFF (büyük-endian) veya 0xFF 0xFE (küçük-endian). – javanna

2
private static char[] UTF32BE = { 0x0000, 0xFEFF }; 
private static char[] UTF32LE = { 0xFFFE, 0x0000 }; 
private static char[] UTF16BE = { 0xFEFF }; 
private static char[] UTF16LE = { 0xFFFE }; 
private static char[] UTF8 = { 0xEFBB, 0xBF }; 

private static boolean removeBOM(Reader reader, char[] bom) throws Exception { 
    int bomLength = bom.length; 
    reader.mark(bomLength); 
    char[] possibleBOM = new char[bomLength]; 
    reader.read(possibleBOM); 
    for (int x = 0; x < bomLength; x++) { 
     if ((int) bom[x] != (int) possibleBOM[x]) { 
      reader.reset(); 
      return false; 
     } 
    } 
    return true; 
} 

private static void removeBOM(Reader reader) throws Exception { 
    if (removeBOM(reader, UTF32BE)) { 
     return; 
    } 
    if (removeBOM(reader, UTF32LE)) { 
     return; 
    } 
    if (removeBOM(reader, UTF16BE)) { 
     return; 
    } 
    if (removeBOM(reader, UTF16LE)) { 
     return; 
    } 
    if (removeBOM(reader, UTF8)) { 
     return; 
    } 
} 

kullanımı:

// xml can be read from a file, url or string through a stream 
URL url = new URL("some xml url"); 
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream())); 
removeBOM(bufferedReader);