2011-03-18 76 views
5

我有一个XML与utf8编码。 而这个文件包含了BOM的一个文件的开头。 因此,在解析期间,我遇到了org.xml.sax.SAXParseException:在prolog中不允许使用内容。 我无法从文件中删除这3个字节。 我无法加载文件到内存中,并在这里删除它们(文件很大)。 因此,出于性能方面的原因,我使用SAX解析器,如果它们出现在“”标签之前,只想跳过这3个字节。 我应该为此继承InputStreamReader吗?为什么org.apache.xerces.parsers.SAXParser不会跳过utf8编码xml中的BOM?

我是新来的java - 请给我正确的方式。

+0

的[字节顺序标记螺丝可能重复了文件阅读在Java](http://stackoverflow.com/questions/1835430/byte-order-mark-screws-up-file-reading-in-java) – 2013-10-07 16:56:37

回答

4

之前已经出现了这个问题,当我遇到Stack Overflow时,我发现了the answer。链接的答案使用PushbackInputStream来测试BOM。

1

我已经经历了同样的问题,我已经用这个代码解决它:

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

这是为UTF8 ...我认为UTF16会有所不同(我相信它只有2个字节)? – Trinition 2011-03-25 19:54:36

+0

很抱歉。是的,UTF16的BOM只有两个字节:0xFE 0xFF(big-endian)或0xFF 0xFE(little-endian)。 – javanna 2011-04-01 06:48:44

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

用法:

// 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); 
相关问题