【问题标题】:Java compress/decompress large files (>1gb)Java 压缩/解压大文件 (>1gb)
【发布时间】:2012-06-19 19:49:27
【问题描述】:

我在 android 中创建了一个应用程序,允许用户压缩和解压缩文件,我使用了包 java.util.zip。一切正常。速度,文件与目录一起完全压缩和解压缩。唯一的问题是应用程序无法压缩/解压缩大文件(大于 1gb)。

我认为问题在于我的buffer 的大小。我见过的其他代码,其缓冲区的值为 1024 或 2048 或 8192,但我的缓冲区值基于所选文件的大小(只是为了使其灵活)。但是一旦用户选择了一个大文件(大小超过 8 位),就会出现错误。我在网上搜索过,也在这个网站上搜索过,但我找不到答案。我的问题与此类似:

To Compress a big file in a ZIP with Java

感谢您以后的帮助! :)

编辑:

感谢 cmets 和答案。它真的帮了很多忙。我认为 BUFFER 在 java 中的压缩/解压缩意味着文件的大小,所以在我的程序中,我使缓冲区大小变得灵活(缓冲区大小 = 文件大小)。有人能解释一下缓冲区是如何工作的,这样我就可以理解为什么BUFFER 有一个固定值是可以的。我也想弄清楚为什么其他人说如果缓冲区大小为 8k 或其他情况会好得多。非常感谢! :)

【问题讨论】:

  • 请发布您的代码 - 特别是您选择缓冲区大小的部分。我怀疑你的缓冲区最终太大了。
  • 无需根据文件大小调整缓冲区大小。如果有的话,它需要调整以匹配它下面的 I/O 层。这很棘手,可能不便携。只要有一个固定的缓冲区大小。
  • 多项式,你的权利就是我的情况。由于 Thilo 的评论,我意识到我误解了buffer 的功能。对你们俩+1。所以这意味着缓冲区的固定值可以压缩/解压缩任何大小的文件?那么不同缓冲区大小的目的是什么? 1024、2048、8192等等?

标签: java android file compression


【解决方案1】:

如果将缓冲区的大小调整为文件大小,则意味着只要文件大小太大而无法使用内存,就会出现 OutOfMemoryError。

使用正常的缓冲区大小并让它发挥作用 - 以流式方式缓冲数据,一次一个块,而不是一次全部缓冲。

解释见BufferedOutputStream的文档:

该类实现了一个缓冲的输出流。通过设置这样一个 输出流,应用程序可以将字节写入底层输出 流,而不必引起对底层系统的调用 写入的每个字节。

所以使用缓冲比非缓冲写入效率更高。

write 方法:

通常此方法将给定数组中的字节存储到此 流的缓冲区,将缓冲区刷新到底层输出流 如所须。如果请求的长度至少与此一样大 但是,流的缓冲区,然后此方法将刷新缓冲区并 将字节直接写入底层输出流。

每次写入都会导致内存缓冲区填满,直到缓冲区已满。当缓冲区已满时,它会被刷新并清除。如果使用非常大的缓冲区,则会导致在刷新之前将大量数据存储在内存中。如果您的缓冲区与输入文件的大小相同,那么您是说您需要在刷新之前将整个内容读入内存。使用默认缓冲区大小通常就可以了。会有更多的物理写入(刷新);避免内存爆炸。

通过允许您指定特定的缓冲区大小,API 可以让您在内存消耗和 i/o 之间选择适当的平衡,以适合您的应用程序。如果您调整应用程序的性能,您最终可能会调整缓冲区大小。但是默认大小在很多情况下都是合理的。

【讨论】:

  • 良好的缓冲区大小约为 8K
  • 是的,这就是我的情况。内存不足错误。你能向我解释一下缓冲区是如何工作的吗?因为我认为缓冲区大小必须等于文件的大小。非常感谢!
  • 康斯坦丁,感谢您的建议!但是你能向我解释为什么让我有更好的理解。谢谢! :)
【解决方案2】:

听起来简单地设置缓冲区的最大大小会有所帮助,例如:

//After calculating the buffer size bufSize:
bufSize = Math.min(bufSize, MAXSIZE);

【讨论】:

  • 为什么要让缓冲区更大?
  • @Thilo 不知道,8k 以上的缓冲区大小通常提供的好处很少。我只是假设 John 想使用可变缓冲区,因为这就是他正在做的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-30
  • 2022-07-27
  • 2013-03-09
相关资源
最近更新 更多