将 DynamoDB table 中的现有字符串压缩为字符串:ZipException:不是 GZIP 格式

Compress an existing string in DynamoDB table to a string : ZipException: Not in GZIP format

我们想在 DynamoDB table 中压缩一个大字符串,它是一个 JSON 对象。

我只想用压缩字符串替换它。我查看了 DynamoDB 文档,它使用 ByteBuffer 直接存储,如前所述 here.

但由于我不想保存 ByteArray,而是存储原始字符串的压缩字符串版本,因此我对其进行了修改。

这是我所做的:

public class GZIPStringCompression {
    public static String compress(String data) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(data.length());
        GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
        gzipOutputStream.write(data.getBytes());
        gzipOutputStream.close();
        return byteArrayOutputStream.toString();
    }

    public static String decompress(String compressed) throws IOException {
        ByteArrayInputStream bis = new ByteArrayInputStream(compressed.getBytes());
        GZIPInputStream gis = new GZIPInputStream(bis);
        BufferedReader br = new BufferedReader(new InputStreamReader(gis, StandardCharsets.UTF_8));
        StringBuilder sb = new StringBuilder();
        String line;
        while((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        gis.close();
        bis.close();
        return sb.toString();
    }
}

这给出了异常:

Exception in thread "main" java.util.zip.ZipException: Not in GZIP format
    at java.base/java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:165)
    at java.base/java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:79)
    at java.base/java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:91)
    at GZIPStringCompression.decompress(MyClass.java:41)
    at MyClass.main(MyClass.java:16)

我不确定我想要的是否可行,这就是为什么,想在这里确认一下。


更改为:

class GZIPStringCompression {
    public static String compress(String data) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(data.length());
        GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
        gzipOutputStream.write(data.getBytes());
        gzipOutputStream.close();
        return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
    }

    public static String decompress(String compressed) throws IOException {

        ByteArrayInputStream bis = new ByteArrayInputStream(Base64.getDecoder().decode(compressed));
        GZIPInputStream gis = new GZIPInputStream(bis);
        BufferedReader br = new BufferedReader(new InputStreamReader(gis, StandardCharsets.UTF_8));
        StringBuilder sb = new StringBuilder();
        String line;
        while((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        gis.close();
        bis.close();
        return sb.toString();
    }
}

这在某种程度上奏效了。这是一个可靠的解决方案吗?

你的第一个解决方案没有用,因为你想获取一个字节数组(8 位字节数组)并将其分配给一个字符串属性(基本上是一个 unicode 字符数组)。这没有意义可能会导致对您的字节进行各种不需要的操作,从而使它们在您读回时无法使用。

您将字节数组转换为 base-64 编码的方法(基本上是 ASCII 的一个子集)有效,因为 ASCII 字符确实可以在不进行任何操作的情况下表示为字符串,并且可以像写入时一样读回.

既然你提到这是针对 DynamoDB 的,我应该补充一下 DynamoDB 除了“字符串”类型之外还有“二进制”类型,你可以直接使用它。在 Java 中,您可以将字节数组直接分配给此类型的属性 - 而无需尝试将其“转换”为字符串。