0

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

在 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

4

1 回答 1

1

字符编码指定由字符组成的文本如何转换为字节,反之亦然。如您所知,有不同的字符编码,例如 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 的有效字符,甚至会出现异常。

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

你要做的是:

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

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

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

于 2015-02-12T14:15:59.733 回答