有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java无法转换Base64字符串并将其正确解压缩

我有Base64字符串。我试图解码它,然后解压缩它

String textToDecode = "H4sIAAAAAAAAAAEgAN//0JTQtdGC0LDQu9C40LfQuNGA0L7QstCw0L3QvdGL0LmRCuyiIAAAAA==\n";
byte[] data = Base64.decode(textToDecode, Base64.DEFAULT);
String result = GzipUtil.decompress(data);

我用于解压缩的代码:

public static String decompress(byte[] compressed) throws IOException {
    final int BUFFER_SIZE = 32;
    ByteArrayInputStream is = new ByteArrayInputStream(compressed);
    GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
    StringBuilder string = new StringBuilder();
    byte[] data = new byte[BUFFER_SIZE];
    int bytesRead;
    while ((bytesRead = gis.read(data)) != -1) {
        string.append(new String(data, 0, bytesRead));
    }
    gis.close();
    is.close();
    return string.toString();
}

我应该得到这个字符串:

Детализированный

相反,我得到的是带有问号符号的字符串:

Детализирован��ый

我犯了什么错?如何解决呢


共 (3) 个答案

  1. # 1 楼答案

    如果只处理流,则可以避免编码问题,这几行代码应该可以很好地完成这项工作

     public static String decompress(byte[] compressed) throws IOException {
            try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
                try (GZIPInputStream gis = new GZIPInputStream(
                        new ByteArrayInputStream(compressed))) {
                    org.apache.commons.compress.utils.IOUtils.copy(gis, bos);
                }
                return bos.toString();
            }
        }
    
  2. # 2 楼答案

    问题可能在这里:

      string.append(new String(data, 0, bytesRead))
    

    您正在使用默认字符编码将字节解码为Java字符串。如果(当前)默认编码与将原始字符编码为字节时使用的编码不同(在压缩等之前),则可能会得到无法正确解码的字节。然后,解码器将用解码器的替换字符替换它们;i、 默认情况下为'\uFFFD'

    如果这是问题所在,那么解决方案就是找出正确的字符编码是什么,并使用String(byte[], int, int, Charset)创建String

  3. # 3 楼答案

    一个问题是,当从字节转换为字符串(内部Unicode)时 没有给出编码。对于UTF-8这样的多字节编码,不能获取固定数量的字节(如32个字节),然后在最后获得有效序列

    你经历了半序列的丢失。因此,编码可能是UTF-8

    final int BUFFER_SIZE = 32;
    ByteArrayInputStream is = new ByteArrayInputStream(compressed);
    GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] data = new byte[BUFFER_SIZE];
    int bytesRead;
    while ((bytesRead = gis.read(data)) != -1) {
        baos.write(data, 0, bytesRead);
    }
    gis.close();
    return baos.toString("UTF-8"); // Or "Windows-1251" ...
    

    上面的代码消除了缓冲区边界问题,并指定了编码,因此相同的代码在不同的计算机上运行

    请记住:

    • new String(bytes, encoding)
    • string.getBytes(encoding)