【问题标题】:Is there a way to recover a byte array that represents a String, that is saved as a String with a different encoding有没有办法恢复表示字符串的字节数组,该数组保存为具有不同编码的字符串
【发布时间】:2013-03-18 23:20:38
【问题描述】:

我们有一个保存字节数组 (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) �

【问题讨论】:

    标签: utf-8 character-encoding


    【解决方案1】:

    很遗憾,不可能,并非在所有情况下都可能。

    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 解码器将用替换字符替换所有格式错误的字节序列(甚至中止解码,具体取决于解码器及其设置)。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2019-10-24
        • 1970-01-01
        • 2020-09-17
        • 2019-09-06
        • 2020-10-18
        • 1970-01-01
        • 2015-09-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多