2009-01-14 37 views
21

我正在使用JAXP生成並解析從數據庫中加載了一些字段的XML文檔。使用Java和UTF-8編碼生成有效的XML

代碼序列化XML:

DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
Document doc = builder.newDocument(); 
Element root = doc.createElement("test"); 
root.setAttribute("version", text); 
doc.appendChild(root); 

DOMSource domSource = new DOMSource(doc); 
TransformerFactory tFactory = TransformerFactory.newInstance(); 

FileWriter out = new FileWriter("test.xml"); 
Transformer transformer = tFactory.newTransformer(); 
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); 
transformer.transform(domSource, new StreamResult(out)); 

代碼來解析XML:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
factory.setNamespaceAware(true); 
DocumentBuilder builder = factory.newDocumentBuilder(); 
Document doc = builder.parse("test.xml"); 

我會遇到以下異常:

[Fatal Error] test.xml:1:4: Invalid byte 1 of 1-byte UTF-8 sequence. 
Exception in thread "main" org.xml.sax.SAXParseException: Invalid byte 1 of 1-byte UTF-8 sequence. 
    at org.apache.xerces.parsers.DOMParser.parse(Unknown Source) 
    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source) 
    at javax.xml.parsers.DocumentBuilder.parse(Unknown Source) 
    at com.test.Test.xml(Test.java:27) 
    at com.test.Test.main(Test.java:55) 

的字符串文本包括U元音變音和o變音(字符代碼0xFC和0xF6)。這些是導致錯誤的字符。當我自己逃脫字符串使用ü和ö那麼問題就會消失。當我寫出XML時,其他實體會自動編碼。

如何在不替代這些字符的情況下正確書寫/讀取輸出?

(我讀過以下問題已:

How to encode characters from Oracle to XML?

Repairing wrong encoding in XML files

回答

31

使用一個FileOutputStream而不是一個FileWriter。

後者應用自己的編碼,這幾乎肯定不是UTF-8(取決於您的平臺,可能是Windows-1252或IS-8859-1)。

編輯(現在我有一些時間):

未經序幕的XML文檔被允許被編碼爲UTF-8或UTF-16。通過序言,可以指定其編碼(序言只能包含US-ASCII字符,所以序言總是可讀的)。

讀者處理字符;它將解碼底層InputStream的字節流。因此,當您將Reader傳遞給解析器時,您告訴它您已經處理了編碼,因此解析器將忽略序言。當你傳遞一個InputStream(它讀取字節)時,它不會做這個假設,並且會看序言來定義編碼 - 如果它不在那裏,則默認爲UTF-8/UTF-16。

我從來沒有嘗試讀取以UTF-16編碼的文件。我懷疑解析器會查找字節順序標記(BOM)作爲文件的前2個字節。

+0

不錯,也很容易,我確實想過改成這個,但放棄了這個想法,因爲我沒有看到在構造函數中指定編碼的方法。它工作得很好,謝謝。 – 2009-01-14 15:31:04

+0

我用FileWriter一次在腳下開槍自殺...... +1 – 2009-01-14 16:03:47

5

那麼,肯定0xFC0xF6是無效的UTF-8字符。這些應該已經被確定爲兩個字節序列:0x3CBC0x3CB6

最有可能的問題是,當字符的原始來源不是UTF-8時,原始來源被定義爲UTF-8