簡體   English   中英

我有UTF-8-但仍然收到“ 1字節UTF-8序列的無效字節1”

[英]I have UTF-8 - but still get “Invalid byte 1 of 1-byte UTF-8 sequence”

我動態創建一個XML String(不讀取文件)。 然后,我使用Cocoon 3將其通過FOP轉換為PDF。 Xerces在中間的某個地方運行。 當我使用硬編碼的東西時,一切正常。 一旦我將德國的Umlaut放入數據庫,並用該數據豐富了我的xml,我就會得到:

Caused by: org.apache.cocoon.pipeline.ProcessingException: Can't parse the XML string.
at org.apache.cocoon.sax.component.XMLGenerator$StringGenerator.execute(XMLGenerator.java:326)
at org.apache.cocoon.sax.component.XMLGenerator.execute(XMLGenerator.java:104)
at org.apache.cocoon.pipeline.AbstractPipeline.invokeStarter(AbstractPipeline.java:146)
at org.apache.cocoon.pipeline.AbstractPipeline.execute(AbstractPipeline.java:76)
at de.grobmeier.tab.webapp.modules.documents.InvoicePipeline.generateInvoice(InvoicePipeline.java:74)
... 87 more

Caused by: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 1 of 1-byte UTF-8 sequence.
    at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:684)
    at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:554)

然后,我調試了我的應用程序,發現我的“Ä”(來自數據庫)的字節值為196,十六進制為C4。 這是我根據此期望的結果: http : //www.utf8-zeichentabelle.de/

我不知道為什么我的代碼失敗。

然后,我嘗試手動添加BOM,如下所示:

byte[] bom = new byte[3];
bom[0] = (byte) 0xEF;
bom[1] = (byte) 0xBB;
bom[2] = (byte) 0xBF;
String myString = new String(bom) + inputString;

我知道這不是很好,但是我嘗試了-當然失敗了。 我試圖在前面添加一個xml標頭:

<?xml version="1.0" encoding="UTF-8"?>

也失敗了。 然后,我將其合並。 失敗了

畢竟我嘗試過這樣的事情:

xmlInput = new String(xmlInput.getBytes("UTF8"), "UTF8");

實際上,它什么也沒做,因為它已經是UTF-8。 仍然失敗。

那么...有什么想法我做錯了什么以及Xerces對我的期望是什么?

謝謝克里斯蒂安

如果您的數據庫僅包含一個字節(值0xC4),則說明您未使用UTF-8編碼。

字符“帶DIAERESIS的拉丁文大寫字母A”的代碼點值為U + 00C4,但UTF-8不能在單個字節中對其進行編碼。 如果檢查UTF8-zeichentabelle.de上的第三列“ UTF-8(十六進制)”,您會看到UTF-8將其編碼為0xC3 84(兩個字節)。

請閱讀Joel的文章“ 絕對絕對要每個軟件開發人員絕對肯定地了解Unicode和字符集(無借口!) ”以獲取更多信息。


編輯:克里斯蒂安自己找到了答案; 原來,這是Cocoon 3 SAX組件中的問題(我想這是Alpha 3版本)。 事實證明,如果將XML作為字符串傳遞給XMLGenerator類,則在SAX解析期間會出問題,從而導致混亂。

查找了代碼以找到Cocoon-stax中的實際問題:

if (XMLGenerator.this.logger.isDebugEnabled()) {
    XMLGenerator.this.logger.debug("Using a string to produce SAX events.");
}
XMLUtils.toSax(new ByteArrayInputStream(this.xmlString.getBytes()), XMLGenerator.this.getSAXConsumer();

如您所見,調用getBytes()將使用JRE的默認編碼創建一個Byte數組,該數組隨后將無法解析。 這是因為XML聲明自己為UTF-8,而數據現在又以字節為單位,並且可能使用Windows代碼頁。

解決方法是,可以使用以下方法:

new org.apache.cocoon.sax.component.XMLGenerator(xmlInput.getBytes("UTF-8"),
       "UTF-8");

這將觸發正確的內部動作(如Christian通過試驗API所發現的)。

我在Apache的錯誤跟蹤器中打開了一個問題

編輯2:該問題已修復,將包含在即將發布的版本中。

您在該頁面上看到的C4指的是Unicode代碼點U+00C4 在UTF-8中用來表示這樣的代碼點的字節序列不是"\\xC4" 您想要的是UTF-8(十六進制)列中的內容,即"\\xC3\\x84"

因此,您的數據不在UTF-8中。

您可以在此處閱讀有關如何以UTF-8編碼數據的信息

我正在將Windows 7和TextPad作為文本編輯器運行,以手動構建xml數據文件。 我正在獲取MalformedByteSequenceException 我在xml文件中的規格是UTF-8。 閑逛之后,我發現我的編輯器有一個工具“工具...轉換為DOS”。 我這樣做了,重新保存了文件,但異常消失了,我的代碼運行良好。

然后,我在編輯器中查看了該文件類型的默認編碼。 它是ASCII,但是當我將xml編碼參數更改為ASCII時,我得到了另一個不同的MalformedByteSequenceException

因此,在Windows系統上,您可以嘗試將xml編碼保留為UTF-8,但保存文件編碼的DOS。 我沒有進一步探討其工作原理。

暫無
暫無

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

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