Java字符编码,ISO到UTF的转换

Posted

技术标签:

【中文标题】Java字符编码,ISO到UTF的转换【英文标题】:Java Character encoding, ISO to UTF conversion 【发布时间】:2015-02-12 14:04:31 【问题描述】:

该主题已成为许多讨论的目标,但我们仍然看到新的主题出现。 我的场景如下:

在 Linux 服务器上运行的 Java 框架,其中 UTF-8 是 JVM 中的默认字符编码。该框架由一些接收要处理的 Tibco RV 消息的服务组成。其中一些消息包含非 ASCII 字符并从 Windows 服务器发送,ISO8859-1 是创建消息时使用的编码。 现在,当从 Tib rv 消息中提取数据时,有问题的字段作为 Java 对象“到达”并且需要转换为字符串......在这里我还不能提取包含非的 ISO8859-1 字符串以正确的方式将 ASCII 字符(瑞典语“å”、“ä”、“ö”)转换为 UTF-8 字符串。 我尝试过使用以下方法:

String isoStreet = new String(response.get("street").toString().getBytes(StandardCharsets.ISO_8859_1),java.nio.charset.StandardCharsets.UTF_8);

我也尝试在 java.nio 包中使用编码器/解码器,但没有成功。

另外有趣的是,我正在使用 PuttY 连接到托管和运行服务的服务器。从那里我有可能从 shell 发出直接的 Tibco rv 请求(使用 tibcorvsend 客户端),似乎我需要在登录之前在 PuttY(Window_>Translation)中将远程字符集设置为 ISO8859-1服务器并发出 Tib rv 请求 - 完成后,这些非 ASCII 字符在响应中显示正确,无论我在远程 Linux 服务器中设置什么编码。 在这种情况下,使用 'export LC_ALL=en_US.UTF-8' 或 'export LC_ALL=sv_SE.iso88591' 无关紧要......只有我在 PuttY 中设置的远程编码......

这应该意味着响应消息看起来不错,并且至少 shell 能够输出正确的字符。但是当在 Java VM 内部(使用 Java 服务)时,我猜在 Watch 视图中调试和查看响应对象(不希望转换为字符串)时,响应字段被悄悄地推送到​​字符串中......不确定你是否可以关注我,如果不是,我可能会在需要时尝试更清楚......

关于这个问题的任何意见,任何人

问候 /R

【问题讨论】:

【参考方案1】:

character encoding 指定由字符组成的文本如何转换为字节,反之亦然。如您所知,有不同的字符编码,例如 ASCII、ISO-8859-1 和 UTF-8。

字符串由字符组成。在某些时候,您希望将这些字符转换为字节,以便您可以通过网络发送它们、将它们存储在文件中或进行任何您想做的事情。您使用字符编码将字符串转换为字节。而在接收字节的另一端,您使用相同的字符编码将字节转换回字符串中的字符。

让我们看看为什么像您发布的那一行是不正确的。让我们先重写它,以便我可以解释部分:

String street = response.get("street").toString();
byte[] streetBytes = street.getBytes(StandardCharsets.ISO_8859_1);
String isoStreet = new String(streetBytes, StandardCharsets.UTF_8);

在第一行中,您从响应中获取一些数据并将其转换为字符串。 (response.get("street") 返回什么?)。

在第二行中,您使用 ISO-8859-1 字符集对该字符串进行编码。您将获得一个字节数组,其中包含字符串中字符的有效 ISO-8859-1 字符代码。

在第三行中,您将字节转换为字符串,并假装这些字节是 UTF-8 字节。这显然是错误的,因为字节是 ISO-8859-1 数据而不是 UTF-8 数据。当你这样做时,你可能会得到错误的字符,如果字节数组包含的字节序列不是 UTF-8 的有效字符,甚至会出现异常。

需要注意的一点是,字符串仅由 字符 组成。字符串本身没有编码。您使用字符编码将字符串转换为字节,反之亦然。您不能“更改字符串的字符编码”,因为字符编码根本不是字符串的属性。就像一个数字本质上不是十进制或十六进制一样 - 它们只是表示同一数字的不同方式。

你要做的是:

在您编写消息时,请确保使用正确的字符编码将字符串转换为字节。

在您阅读消息时,请确保使用正确的字符编码将字节转换为字符串。

不要使用平台的默认字符编码将某些内容读入字符串,然后尝试“转换字符串”。那是行不通的。

【讨论】:

感谢您的回复... 一个问题是,我对我们获得的回复的创建方式没有任何影响。它是一个外部系统,一个运行在 Windows 服务器上的 LDAP 服务器。 response.get("fieldName") 将返回一个对象(如果 Tibco 响应消息中不存在该字段,则返回 null)但它实际上是一个字符串字段 - Tibco RV 消息中的所有字段都作为对象发送,但对象更多字符串、整数等的容器。不过,不知道如何将响应消息中的这些字符转换为 Java 字符串(或字节 []) 嗯,不确定这是否是对您的回复做出回应的正确方式......也许我应该发布一个答案??? 您必须分析您的代码并准确找出消息中的内容以及您从中得到的内容。希望我的回答能帮助你理解字符编码,从而有效解决这个问题。

以上是关于Java字符编码,ISO到UTF的转换的主要内容,如果未能解决你的问题,请参考以下文章

java怎样实现将GB2312编码的字符串转换为ISO-8859-1编码的字符串

如何将gbk 编码的字符串转换成 utf

使用C ++将越南语字符编码为USASCII,ISO88591,UTF8,UTF16BE,UTF16LE,UTF16

java获取字符串编码和转换字符串编码

如何将汉字转换为iso-8859-1的字符串 - PHP进阶讨论

提升Java字符串编码解码性能的技巧