【问题标题】:Convert Zip to Store compression将 Zip 转换为存储压缩
【发布时间】:2013-12-28 03:46:47
【问题描述】:

我有一个压缩文件file.zip。有没有办法改变要存储的文件的压缩级别(不压缩)。

我已经编写并尝试了以下代码,它可以工作,但我将在内存和存储受限且可能没有足够空间的环境中运行它。我正在使用 zip4j 库。

此代码将输入的 zip 解压缩到一个文件夹,然后以存储压缩级别对其进行重新压缩。这样做的问题是,在执行的某个时间点,存储中有 3 个 zip 副本,这是一个问题,因为空间是一个限制。

try {
            String zip = "input.zip";
            final ZipFile zipFile = new ZipFile(zip);
            zipFile.extractAll("dir");
            File file = new File("dir");
            ZipParameters params = new ZipParameters();
            params.setCompressionMethod(Zip4jConstants.COMP_STORE);
            params.setIncludeRootFolder(false);

            ZipFile output = new ZipFile(new File("out.zip"));

            output.addFolder(file, params);
            file.delete();
            return "Done";
        } catch (Exception e) {
            e.printStackTrace();
            return "Error";
        }

那么对于解决这个问题的另一种方法有什么建议吗?或者对我当前的代码进行一些速度或内存优化?

【问题讨论】:

  • 所以您是说您想使用 Zip 作为容器格式但不压缩内容,但您担心使用太多存储空间?不清楚你在这里问什么。
  • 是的,我有一个压缩的zip文件,我想把它变成容器格式,即去掉压缩。我当前代码的问题在于它将输入提取到一个文件夹中,然后制作一个新的 zip,在执行的某个时间点有 3 个副本,这会消耗大量内存

标签: java android compression zip


【解决方案1】:

作为替代方案,我们可以从内存中的 zip 文件或临时文件中一个一个地读取文件,就像这里

    ZipInputStream is = ...
    ZipOutputStream os = ...
    os.setMethod(ZipOutputStream.STORED);
    int bSize = ... calculate max available size 
    byte[] buf = new byte[bSize];
    for (ZipEntry e; (e = is.getNextEntry()) != null;) {
        ZipEntry e2 = new ZipEntry(e.getName());
        e2.setMethod(ZipEntry.STORED);
        int n = is.read(buf);
        if (is.read() == -1) {
            // in memory
            e2.setSize(n);
            e2.setCompressedSize(n);
            CRC32 crc = new CRC32();
            crc.update(buf, 0, n);
            e2.setCrc(crc.getValue());
            os.putNextEntry(e2);
            os.write(buf, 0, n);
            is.closeEntry();
            os.closeEntry();
        } else {
            // use tmp file
        }
    }

在内存中读取应该更快

【讨论】:

  • 谢谢,我尝试执行您的代码,只传输了输入 zip 中的第一个文件。
  • 尝试将 buf 大小增加到某个较大的值,我假设您的文件大于缓冲区并被跳过
【解决方案2】:

几个小时后,我终于通过输入流玩弄了它。

try {
            final ZipFile zipFile = new ZipFile("input.zip");
            File output = new File("out.zip");
            byte[] read = new byte[1024];
            ZipInputStream zis = new ZipInputStream(new FileInputStream(zip));
            ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(output));
            ZipEntry ze;
            zos.setLevel(ZipOutputStream.STORED);
            zos.setMethod(ZipOutputStream.STORED);
            while((ze = zis.getNextEntry()) != null) {
                int l;
                zos.putNextEntry(ze);
                System.out.println("WRITING:  " + ze.getName());
                while((l = zis.read(read)) > 0) {
                    zos.write(read, 0, l);
                }
                zos.closeEntry();
            }
            zis.close();
            zos.close();
            return "Done";
        } catch (Exception e) {
            e.printStackTrace();
            return "Error";
        }

非常感谢您的回答 Evgeniy Dorofeev,当我读到您的回答时,我真的得到了答案!但是,我更喜欢我的方法,因为它最多只占用 1 MB 的内存(对吗?)。另外,我尝试执行您的代码,只传输了输入 zip 中的第一个文件。

【讨论】:

    猜你喜欢
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多