Java 7zip 压缩字符串

5
我希望将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并打印出来,而不需要生成或读取新文件。

你能分享将定义的字符串压缩成7z并转换为字节数组的代码吗? - Nizam
4个回答

4

如果您已经在使用 commons-compress 进行7zip压缩,那么您可以使用 SeekableInMemoryByteChannel 包装一个字节数组并创建一个 SevenZOutputFile(SeekableByteChannel) 实例。根据 javadoc:

一种 SeekableByteChannel 实现,它包装了一个 byte[]。

当此通道用于写入时,内部缓冲区会增长以容纳传入的数据。自然的大小限制是 Integer.MAX_VALUE 的值。内部缓冲区可以通过 array() 访问。

类似于以下内容:

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

1

这可能有点离题,但假设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 []。

0

当然,您必须对您发布的代码进行几处更改。那段代码是用于压缩文件或文件夹,而您的情况则简单得多。例如,您肯定不需要使用for循环。

我将分解出各个部分供您查看,编码工作就留给您了。

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

其中一个选择是使用ByteArrayInputStream而不是FileInputStream。要初始化ByteArrayInputStream,其字节必须对应于字符串。

请参见以下文章,了解有关如何执行此转换的示例:

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

将输出字节转换为Base64:

有几种方法可以实现,详见此StackOverflow主题:

如何在Java中将字节数组转换为Base64?

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

您需要使用带有SeekableByteChannel接口输入的SevenZOutputFile构造函数。您的SeekableByteChannel实现将必须由某种字节数组或流支持。您可以使用以下实现:

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

从非文件中获取SevenZArchiveEntry:

尽管SevenZOutputFile类似乎没有提供这样的功能,但是如果您查看其源代码,您会注意到可以手动创建一个SevenZArchiveEntry而不需要任何中介,因为它有一个空构造函数。您需要“假装”它仍然是实际的文件,但这不应该成为问题。

SevenZArchiveEntry的源代码:

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


0
我发现有人已经实现了这段代码。
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;

/**
 * the SevenZ Util
 *
 * @author ph3636
 */
public class SevenZUtil {

    private static final int BUFFER_SIZE = 8192;

    public static byte[] compress(byte[] bytes) {
        if (bytes == null) {
            throw new NullPointerException("bytes is null");
        }
        SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel();
        try (SevenZOutputFile z7z = new SevenZOutputFile(channel)) {
            SevenZArchiveEntry entry = new SevenZArchiveEntry();
            entry.setName("sevenZip");
            entry.setSize(bytes.length);
            z7z.putArchiveEntry(entry);
            z7z.write(bytes);
            z7z.closeArchiveEntry();
            z7z.finish();
            return channel.array();
        } catch (IOException e) {
            throw new RuntimeException("SevenZ compress error", e);
        }
    }

    public static byte[] decompress(byte[] bytes) {
        if (bytes == null) {
            throw new NullPointerException("bytes is null");
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(bytes);
        try (SevenZFile sevenZFile = new SevenZFile(channel)) {
            byte[] buffer = new byte[BUFFER_SIZE];
            while (sevenZFile.getNextEntry() != null) {
                int n;
                while ((n = sevenZFile.read(buffer)) > -1) {
                    out.write(buffer, 0, n);
                }
            }
            return out.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException("SevenZ decompress error", e);
        }
    }
}

<commons-compress.version>1.22</commons-compress.version>
<xz.version>1.9</xz.version>

<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>${commons-compress.version}</version>
</dependency>
<dependency>
            <groupId>org.tukaani</groupId>
            <artifactId>xz</artifactId>
            <version>${xz.version}</version>
</dependency>

参考:SevenZUtil.java


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接