未知的UTF-8代码单元关闭双引号

时间:2013-01-17 12:28:06

标签: java xml utf-8 saxparser

我的问题如下。我正在读取一个XML文件,其文本节点部分包含打开和关闭双引号的UTF-8版本。提取文本,缩短为3999字节并放入新的XML格式,然后将其保存为文件。

虽然输入文件中的Notepad ++正确显示了两个符号,但输出文件包含无效的utf-8字符,甚至Notepad ++都无法显示。

打开的双引号被正确打印,但结尾的双引号被毁掉了。

使用十六进制编辑器,我发现代码单元以某种方式从

更改
  

E2 80 9D

输入文件中的

  

E2 80 3F

在输出文件中。 我正在使用sax-parser进行xml解析。

是否有任何可能导致此类行为的已知错误?

3 个答案:

答案 0 :(得分:1)

E2 80 9D是UTF-8的有效字节序列,给出'”' = \u201d'。 您可以看到这一点,因为所有高位都已设置。 这是UTF的一个值得称道的安全属性,所以不能错误地在这样的序列中找到ASCII,比如'/'。

在第二个序列中,3F('?')在字节中没有设置高位,所以是错误的。 这意味着读数出错(问号)左右。 喜欢转换两次,更换。特别是9D在扩展的Windows Latin-1又称Cp1252(80 - 9F)。

答案 1 :(得分:1)

不是已知的错误,但是在读取文件或编写文件时将编码保留为常见错误 - 导致使用的平台默认编码在这种情况下为Windows-1252。

最初读取文件时,应指定UTF-8解码,写入新文件时,应指定UTF-8编码。如果你发布你的实现,我可以纠正它。

如何重现:

byte[] quoteutf8 = {(byte)0xE2, (byte)0x80, (byte)0x9D};
String decodedPlatformDefault = new String(quoteutf8, "Windows-1252");
byte[] encodedPlatformDefault = decodedPlatformDefault.getBytes("Windows-1252");

for( byte i : encodedPlatformDefault ) {
    System.out.print(String.format( "%02x ", i ));
   //e2 80 3f   
}

答案 2 :(得分:0)

在从字节数组创建新字符串时以及从字符串返回字节数组时,应始终指定字符集名称。

如果没有,系统的默认字符集将被占用,可能会在任何地方产生问题......

而不是

new String(myByteArray);
//... and...
myString.getBytes();

你应该使用

new String(myByteArray, "UTF-8");
//... and...
myString.getBytes("UTF-8");

例如

Transformer transformer = TransformerFactory.newInstance().newTransformer();

transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");

StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(xmlDocument);
transformer.transform(source, result);

return result.getWriter().toString().getBytes("UTF-8");

从Java 1.6开始,您可以specify a Charset而不是包含charset名称的字符串: