小编典典

Java中的“修复”字符串编码

java

我使用UTF-8编码Stringbyte[]数组创建了一个。
但是,它应该已经使用其他编码创建(Windows-1252)。

有没有办法将此String转换回正确的编码?

我知道如果可以访问原始字节数组很容易做到,但是就我而言,为时已晚,因为它是由封闭的源库提供的。


阅读 216

收藏
2020-10-07

共1个答案

小编典典

关于这是否可行似乎有些困惑,我想我需要提供一个广泛的例子。

该问题声称(初始)输入是byte[]包含Windows-1252编码数据的输入。我称其byte[]
ib为“初始字节”。

在此示例中,我将选择德语单词“Bär”(意为熊)作为输入:

byte[] ib = new byte[] { (byte) 0x42, (byte) 0xE4, (byte) 0x72 };
String correctString = new String(ib, "Windows-1252");
assert correctString.charAt(1) == '\u00E4'; //verify that the character was correctly decoded.

(如果您的JVM不支持该编码,则可以改用ISO-8859-1,因为这三个字母(以及大多数其他字母)在这两种编码中位于同一位置)。

问题继续说明,其他一些代码(在我们的影响范围之外)已经byte[]使用UTF-8编码将其转换为字符串(我将其称为String
is“输入字符串”)。这String是可用于实现我们目标的 唯一输入 (如果is可用,那将是微不足道的):

String is = new String(ib, "UTF-8");
System.out.println(is);

显然这会产生错误的输出“ B”。

目标将是 仅* 提供可用的内容ib(或对其进行正确的解码byte[])。 *is

现在有人声称 _从中is_获取UTF-8编码的字节将返回与初始数组具有相同值的数组:

byte[] utf8Again = is.getBytes("UTF-8");

但这将返回两个字符的UTF-8编码,B并且在重新解释为Windows-1252时肯定会返回错误的结果:

System.out.println(new String(utf8Again, "Windows-1252");

该行产生输出“B�”,这是完全错误的(如果初始数组包含非单词“Bür”,则结果也是相同的输出)。

因此, 在这种情况下, 您将无法撤消该操作,因为信息会丢失。


实际上情况下,这种错误的编码可以撤消。当所有可能的(或至少出现的)字节序列在该编码中有效时,它更有可能起作用。由于UTF-8具有几个字节序列,这些字节序列根本不是有效值,因此您
遇到问题。

2020-10-07