如何解析与java不同编码的字符串

我有一个我从Word文档中读过的字符串。 我认为这是在“Cp1252”编码。 Java使用UTF8。

如何在Cp1252中搜索该字符串中的那些特殊字符并用适当的UTF8字符替换它们?

具体来说,我想用简单的“ – ”替换“En Dash”字符

以下代码块采用来自Word文档的projDateString,并尝试执行此类操作

char[] test = projDateString.getBytes("Cp1252"); for(int i = 0; i < test.length; i++){ System.out.println "test["+ i + "] = " + Integer.toHexString((byte)test[i]); } String projDateString2 = new String(test); projDateString2.replaceAll("\0x96", "\u2013"); System.out.println("projDateString2: " + projDateString) 

我不确定我是否正确设置了projDateString2。 如您所见,当我使用Cp1252编码对字符串进行getBytes时,该破折号的hex值为ffffff96。 如果我使用UTF8获取它,它将以3个hex值而不是一个。

这给了我以下输出:

 test[0] = 30 test[1] = 38 test[2] = 2f test[3] = 32 test[4] = 30 test[5] = 31 test[6] = 30 test[7] = 20 test[8] = ffffff96 test[9] = 20 test[10] = 50 test[11] = 72 test[12] = 65 test[13] = 73 test[14] = 65 test[15] = 6e test[16] = 74 projDateString2: 08/2010 ΓÇô Present 

你可以看到,替换没有做任何事情,println仍然给我垃圾字符而不是明文“ – ”

Java字符串始终使用UTF-16,至少就API而言……但您通常可以将它们视为“Unicode”。 它们是UTF-16这一事实只有在基本多语言平面之外的字符时才真正相关,即Unicode值高于U + FFFF。 它们必须在Java中表示为代理对 。 但我不认为你需要担心这个问题。 因此,只需将字符串中的值视为“Unicode文本”而不​​使用特定的编码…特别是绝对不能使用UTF-8或CP1252。 这些是用于将二进制数据(例如字节数组)转换为文本数据(例如字符串)的编码。

你不应该使用String.getBytes()new String(byte[])而不指定编码 – 这就是问题所在。 那些总是使用平台默认编码 – 这几乎总是错误的选择。

你说你“有一个我从Word文档中读过的字符串” – 你是怎么读的? 它是如何从生活开始的?

如果你有字节并且你知道相关的编码,你应该使用:

 String text = new String(bytes, encoding); 

你永远不必处理使用错误编码创建的字符串 – 如果你到达那个阶段,你几乎肯定会冒信息丢失的风险。 尽可能早地解决问题,而不是稍后尝试修复数据。

接下来要理解的是Java中的String类是不可变的。 在字符串上调用replaceAll 不会更改现有字符串 。 它将返回一个带有替换的字符串。

所以这句话:

 projDateString2.replaceAll("\0x96", "\u2013"); 

永远不会做你想要的。 即使其他一切都是正确的,你应该使用:

 projDateString2 = projDateString2.replaceAll("\0x96", "\u2013"); 

(或类似的东西)。 我不认为它实际上做你想要的,但是当你解决其他问题时你需要注意它。

转换通常通过以下方式完成:

 String properlyEncoded = new String(original.getBytes(originalEncoding), newEncoding); 

请注意,转换期间某些信息不会丢失。

首先,您需要确保正确地从CP1252字节转换为Java的字符表示 (UTF-16)。 由于您正在使用库来解析.docx文件,因此可能会发生这种情况。

现在您需要做的就是调用projDateString.replace('\u2013', '-')并使用返回值执行某些操作。 不需要replaceAll() ,因为你没有使用正则表达式。