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

问题描述 投票:0回答:2

我有一个从 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 编码在字符串上获取字节时,该破折号的十六进制值为 ffffff96。如果我使用 UTF8 获取字节,它会以 3 个十六进制值的形式出现,而不是 1 个。

这给了我以下输出:

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 character-encoding
2个回答
15
投票

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

new String(byte[])

-

这就是问题所在。这些总是使用平台默认编码 - 这几乎是
总是
错误的选择。
你说“有一个我从Word文档中读入的字符串”——你是如何读入的?生命是如何开始的? 如果您有 bytes

并且您知道相关编码,则应该使用:

String text = new String(bytes, encoding);

您永远不必处理使用错误编码创建的字符串 - 如果您到达该阶段,您几乎将面临信息丢失的风险。尽早解决问题,而不是稍后尝试修复数据。

接下来
要理解的是,Java中的
String

类是不可变的。在字符串上调用 replaceAll

不会更改现有字符串

。相反,它将返回一个 new 字符串并进行替换。


所以这个声明:

projDateString2.replaceAll("\0x96", "\u2013"); 永远不会做你想做的事。即使其他一切都正确,您也应该使用:

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

(或类似的东西)。我不认为实际上

做你想做的事,但是当其他一切都解决之后你需要意识到这一点。

转换一般是这样完成的:

String properlyEncoded = new String(original.getBytes(originalEncoding), newEncoding); 请注意,转换过程中有些信息可能会丢失。


3
投票

© www.soinside.com 2019 - 2024. All rights reserved.