Java 字符串的 7zip 压缩

Java 7zip compression of a String

我想在 Java 中将手动定义的字符串压缩为 7z。这样我就可以将它转换为 base64。我发现许多示例将文件压缩到 7z,然后保存到新文件中。

我只是尝试了下一个代码,它正确地获取了文件并进行了压缩:

private static void addToArchiveCompression(SevenZOutputFile out, File file, String dir) throws IOException {
        String name = dir + File.separator + file.getName();
        if (file.isFile()){
            SevenZArchiveEntry entry = out.createArchiveEntry(file, name);
            out.putArchiveEntry(entry);

            FileInputStream in = new FileInputStream(file);
            byte[] b = new byte[1024];
            int count = 0;
            while ((count = in.read(b)) > 0) {
                out.write(b, 0, count);
            }
            out.closeArchiveEntry();

        } else if (file.isDirectory()) {
            File[] children = file.listFiles();
            if (children != null){
                for (File child : children){
                    addToArchiveCompression(out, child, name);
                }
            }
        } else {
            System.out.println(file.getName() + " is not supported");
        }
    }  

但是如何将手动定义的字符串压缩为 7z 并将其转换为 byte[]?那么我可以将 byte[] 转换为 base64 并打印它,而无需生成或读取新文件?

因为您已经在使用包装字节数组的 commons-compress for 7zip compression you can create SevenZOutputFile(SeekableByteChannel) instance with SeekableInMemoryByteChannel。根据 javadoc:

A SeekableByteChannel implementation that wraps a byte[].

When this channel is used for writing an internal buffer grows to accommodate incoming data. A natural size limit is the value of Integer.MAX_VALUE. Internal buffer can be accessed via array().

类似于:

SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(new byte[1024]);
SevenZOutputFile out = new SevenZOutputFile(channel);
// modified addToArchiveCompression(out, ...); for String
// encode channel.array() to Base64

您当然必须对您发布的代码进行几处更改。该代码旨在压缩文件或目录,而您的情况要简单得多。例如,您绝对不需要 for 循环。

我分解了您必须研究的各个部分,并将编码留给您。

将字符串转换为 7z 数据:

其中一个选项是使用 ByteArrayInputStream 而不是 FileInputStreamByteArrayInputStream 必须使用与字符串对应的字节进行初始化。

有关如何进行此转换的示例,请参阅以下文章:

https://www.baeldung.com/convert-string-to-input-stream

正在将输出字节转换为 Base64:

有几种方法,在此 Whosebug 线程中有详细说明:

How do I convert a byte array to Base64 in Java?

将 7z 输出到内存而不是文件:

您将不得不使用 SevenZOutputFile 构造函数,将 SeekableByteChannel 接口作为输入。 SeekableByteChannel 的实现必须由字节数组或各种流支持。您可以使用以下实现:

https://commons.apache.org/proper/commons-compress/apidocs/org/apache/commons/compress/utils/SeekableInMemoryByteChannel.html

从文件以外的东西获取 SevenZArchiveEntry

虽然 SevenZOutputFile class 似乎没有提供执行此操作的工具,但如果您查看其源代码,您会发现您可以手动创建一个 SevenZArchiveEntry没有任何中介,因为它有一个空的构造函数。您必须 "pretend" 它仍然是一个实际文件,但这应该不是问题。

SevenZArchiveEntry 的源代码:

https://commons.apache.org/proper/commons-compress/apidocs/src-html/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.html

这有点离题,但假设 LZMA 是 7zip 的一部分,这可能对您有所帮助:

public static byte[]compress(byte[]arr,int level){
    try {
        ByteArrayOutputStream compr = new ByteArrayOutputStream();
        LZMA2Options options = new LZMA2Options();
        options.setPreset(level); // play with this number: 6 is default but 7 works better for mid sized archives ( > 8mb)
        XZOutputStream out = new XZOutputStream(compr, options);
        out.write(arr);
        out.finish();
        return compr.toByteArray();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

public static byte[]decompress(byte[]bts){
    try {
        ByteArrayInputStream bis = new ByteArrayInputStream(bts);
        XZInputStream is = new XZInputStream(bis);
        ByteArrayInputStream decomp = new ByteArrayInputStream(is.readAllBytes());
        ObjectInputStream ois = new ObjectInputStream(decomp);
        byte data[]= (byte[]) ois.readObject();
        return data;
    } catch (IOException | ClassNotFoundException e) {
        throw new RuntimeException(e);
    }
}

maven 依赖:

    <dependency>
        <groupId>org.tukaani</groupId>
        <artifactId>xz</artifactId>
        <version>1.8</version>
    </dependency>

使用 s.getBytes(StandardCharsets.UTF_8);

将您的字符串转换为 byte[]