【问题标题】:Java 7zip compression of a String字符串的Java 7zip压缩
【发布时间】:2019-10-15 05:42:10
【问题描述】:

我想在 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");
        }
    }  

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

【问题讨论】:

  • 你能分享一下将定义的String压缩成7z并转换成字节数组的代码吗?

标签: java 7zip


【解决方案1】:

由于您已经在使用 commons-compress 进行 7zip 压缩,您可以使用包装字节数组的 SeekableInMemoryByteChannel 创建 SevenZOutputFile(SeekableByteChannel) 实例。根据 javadoc:

一个包装字节[]的 SeekableByteChannel 实现。

当此通道用于写入时,内部缓冲区会增长以容纳传入数据。一个自然的大小限制是 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

【讨论】:

    【解决方案2】:

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

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

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

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

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

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

    将输出字节转换为 Base64:

    有几种方法,在这个 StackOverflow 线程中有详细说明:

    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 类似乎没有提供这样做的工具,但如果您查看它的源代码,您会注意到您可以手动创建SevenZArchiveEntry 而无需任何中介,因为它有一个空的构造函数.您必须“假装”它仍然是一个实际文件,但这不应该成为问题。

    SevenZArchiveEntry的源码:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-13
        • 1970-01-01
        相关资源
        最近更新 更多