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

Der*_*rek 1 java character-encoding

我有一个我从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)
Run Code Online (Sandbox Code Playgroud)

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

这给了我以下输出:

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
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 14

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);
Run Code Online (Sandbox Code Playgroud)

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

接下来的事情要明白的是,String在Java类是不可变的.调用replaceAll字符串不会更改现有字符串.它将返回一个带有替换的字符串.

所以这句话:

projDateString2.replaceAll("\0x96", "\u2013");
Run Code Online (Sandbox Code Playgroud)

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

projDateString2 = projDateString2.replaceAll("\0x96", "\u2013");
Run Code Online (Sandbox Code Playgroud)

(或类似的东西).我认为无论如何它实际上都不会做你想要的,但是当其他一切都被整理出来时你需要意识到它.