有没有办法恢复表示String的字节数组,该字节数组保存为具有不同编码的String

时间:2012-05-14 07:54:14

标签: utf-8 character-encoding

我们有一个数据库,我们保存字节数组(HBase)。 我们所有的字符串都被编码为字节,我们手动进行转换。 但是,一些旧数据被错误地保存了,我想知道是否有办法恢复它们。

发生的事情是我们在ISO_8859_1中有一些原始文本被编码,比方说 但是,将这些字符串保存为字节数组的过程与new String(original_bytes, UTF8).getBytes(UTF8)类似  (而original_bytes将字符串表示为ISO8859_1)

我找不到恢复original_bytes数组的方法。它实际上是否可能?

我尝试使用这个简单的Java示例代码重现它:

String s = "é";
System.out.println("s: " + s);
System.out.println("s.getBytes: " + Arrays.toString(s.getBytes()));
System.out.println("s.getBytes(UTF8): " + Arrays.toString(s.getBytes(Charsets.UTF_8)));
System.out.println("new String(s.getBytes()): " + new String(s.getBytes()));
System.out.println("new String(s.getBytes(), UTF-8): " + new String(s.getBytes(), Charsets.UTF_8));

byte [] iso = s.getBytes(Charsets.ISO_8859_1);
System.out.println("iso " + Arrays.toString(iso));
System.out.println("new String(iso)" + new String(iso));
System.out.println("new String(iso, ISO)" + new String(iso, Charsets.ISO_8859_1));
System.out.println("new String(iso).getBytes()" + Arrays.toString(new String(iso).getBytes()));
System.out.println("new String(iso).getBytes(ISO)" + Arrays.toString(new String(iso).getBytes(Charsets.ISO_8859_1)));
System.out.println("new String(iso, UTF8).getBytes()" + Arrays.toString(new String(iso, Charsets.UTF_8).getBytes()));
System.out.println("new String(iso, UTF8).getBytes(UTF8)" + Arrays.toString(new String(iso, Charsets.UTF_8).getBytes(Charsets.UTF_8)));

输出:(在默认字符集为UTF8的计算机上)

s: é
s.getBytes: [-61, -87]
s.getBytes(UTF8): [-61, -87]
new String(s.getBytes()): é
new String(s.getBytes(), UTF-8): é
iso [-23]
new String(iso)�
new String(iso, ISO)é
new String(iso).getBytes()[-17, -65, -67]
new String(iso).getBytes(ISO)[63]
new String(iso, UTF8).getBytes()[-17, -65, -67]
new String(iso, UTF8).getBytes(UTF8)[-17, -65, -67]
new String(new String(iso).getBytes(), Charsets.ISO_8859_1) �

2 个答案:

答案 0 :(得分:0)

不幸的是,不是,在每种情况下都不可能。

UTF-8有相当多的字节序列是非法的,并且在解码时(通常)会被某些替换字符替换。当您的original_bytes包含任何字节序列时,那些信息肯定会丢失。

您最好的选择是反过来,这可能会让您尽可能接近原始字符串:

byte[] originalISOData = ...;
byte[] badUTF8 = new String(originalISOData, "UTF-8").getBytes("UTF-8");
byte[] partialReconstruction = new String(badUTF8, "ISO-8859-1");

tl; dr 解码非UTF-8数据,因为UTF-8 通常无损操作。有效的UTF-8解码器将用替换字符替换所有格式错误的字节序列(甚至中止解码,具体取决于解码器及其设置)。

答案 1 :(得分:0)

您可以使用Hbase API提供的Bytes类。例如,将字节数组转换为字符串,您可以使用“Bytes.toString(byteArray)”。