我们想要压缩 DynamoDB 表中的一个大字符串,它是一个 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();
}
}
这不知怎的奏效了。这是一个可靠的解决方案吗?
u200e您的第一个解决方案不起作用,因为您想要获取一个字节数组(8 位字节数组)并将其分配给一个 String 属性(基本上是一个 unicode 字符数组)。这没有意义,可能会导致对您的字节进行各种不需要的操作,从而使您在读回它们时无法使用它们。
将字节数组转换为 base-64 编码(基本上是 ASCII 的子集)的方法是有效的,因为 ASCII 字符确实可以在字符串中表示,无需任何操作,并且可以像写入一样读回。
既然您提到这是针对 DynamoDB 的,我应该添加 DynamoDB 除了“字符串”类型之外还有“二进制”类型,您可以使用它。在 Java 中,您可以将字节数组直接分配给这种类型的属性 - 并且不需要尝试将其“转换”为字符串。