如何解析与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()
,因为你没有使用正则表达式。