簡體   English   中英

如何從Java中刪除XML文件中的BOM

[英]How to Remove BOM from an XML file in Java

我需要有關從UTF-8文件中刪除BOM的方法的建議,並創建其余xml文件的副本。

根據我的經驗,由於UTF-8文件中的BOM而導致工具崩潰是非常常見的事情。 我不知道為什么會有這么多的downvotes(但它讓我有機會獲得足夠的投票來贏得一個特殊的SO徽章;)

更嚴重的是:UTF-8 BOM通常沒有多大意義, 它完全有效(盡管不鼓勵)規范。 現在的問題是很多人都不知道BOM在UTF-8中是有效的,因此編寫了不能正確處理這些文件的破壞的工具/ API。

現在您可能有兩個不同的問題:您可能希望從Java處理文件,或者您需要使用Java以編程方式創建/修復其他(損壞的)工具所需的文件。

我在一個咨詢工具中遇到過這樣的情況:幫助台會不斷收到來自用戶的消息,這些消息會導致某些文本編輯器出現問題,而這些編輯器會破壞Java生成的完整有效的UTF-8文件。 因此,我必須通過確保從我們正在處理的每個UTF-8文件中刪除BOM來解決該問題。

我想從文件中刪除BOM,您可以創建一個新文件並跳過前三個字節。 例如:

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

如您所見,文件以“ef bb bf”開頭,這是(完全有效的)UTF-8 BOM。

這是一個獲取文件並通過跳過前三個字節來復制它的方法:

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

請注意,它是“原始的”:您通常希望首先確保您有一個BOM,然后再調用它或“Bad Thinks May Happen”[TM]。

您可以在以后查看您的文件:

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

BOM已經不見了......

現在,如果您只是想透明地刪除已損壞的Java API的BOM,那么您可以使用此處描述的pushbackInputStream為什么org.apache.xerces.parsers.SAXParser不會跳過utf8編碼的xml中的BOM?

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

需要注意的是這個作品,但應當肯定沒有解決更嚴重的問題,你可以有其他工具在工作鏈不與具有BOM UTF-8的文件正常工作。

這里是一個帶有更完整答案的問題的鏈接,也包括其他編碼:

字節順序標記用Java解壓縮文件讀取

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM