文件 "open" 在列表 <File> 中并且内存不足
Files are "open" in a List<File> and get out of memory
我在使用 Java 执行以下操作时遇到问题:
- 创建一个 .xls 文件并在服务器上写入一些内容。
- 将此文件存储到列表中。
- 重复步骤 1 和 2 数千次,得到一个包含数千个 .xls 文件的列表。
- 将文件导出到 .zip 存档中。
我的问题是创建的文件似乎都是"open",而且会内存不足。实际上每个文件只有37kb左右,文件数量只有2000个左右。我觉得不算太多,但每次都失败了。那么有人对这个问题有一些想法吗?非常感谢!
问题是您以错误的方式处理流程。 ZIP 文件不是通过将每个文件读入内存、压缩它然后写入输出来构建的。相反,它一次写入一个文件,只有 目录列表 存储在内存中。在伪代码中,这意味着您正在这样做:
Create Zip Memory Directory
Open Zip File Handle
For Each File In Directory
Open File In Read Mode
Compress File
Write Headers and File To Zip File
Store Info About File in Zip Memory Directory
Close File
End For
Write Zip Memory Directory to Zip File
Close Zip File Handle
这意味着您只需要压缩单个文件所需的内存,并且在任何给定时间您只能打开两个文件。这部分是因为大多数系统用于跟踪打开文件的 space ("handles") 数量有限,因此根据 language/OS/whatever,您实际上可能会耗尽平台的文件句柄限制每个 thread/process/entire 系统。同样,解压通常也是一个文件一个文件地实现。
在 Java 中,您实际上可能正在使用 Zip 实用程序 class,读取每个文件,将其压缩到内存中的某个位置,然后关闭该文件,并循环查找其余文件;在整个过程结束时,将 Zip 文件保存到磁盘。
请参阅 ZipOutputStream 以了解您可以使用的 class。实际上,它的工作原理是接受一个 OutputStream(通过以写入模式打开文件创建),然后循环调用 putNextEntry、write、closeEntry,最后调用 close() 将文件刷新到磁盘。
我在使用 Java 执行以下操作时遇到问题:
- 创建一个 .xls 文件并在服务器上写入一些内容。
- 将此文件存储到列表中。
- 重复步骤 1 和 2 数千次,得到一个包含数千个 .xls 文件的列表。
- 将文件导出到 .zip 存档中。
我的问题是创建的文件似乎都是"open",而且会内存不足。实际上每个文件只有37kb左右,文件数量只有2000个左右。我觉得不算太多,但每次都失败了。那么有人对这个问题有一些想法吗?非常感谢!
问题是您以错误的方式处理流程。 ZIP 文件不是通过将每个文件读入内存、压缩它然后写入输出来构建的。相反,它一次写入一个文件,只有 目录列表 存储在内存中。在伪代码中,这意味着您正在这样做:
Create Zip Memory Directory
Open Zip File Handle
For Each File In Directory
Open File In Read Mode
Compress File
Write Headers and File To Zip File
Store Info About File in Zip Memory Directory
Close File
End For
Write Zip Memory Directory to Zip File
Close Zip File Handle
这意味着您只需要压缩单个文件所需的内存,并且在任何给定时间您只能打开两个文件。这部分是因为大多数系统用于跟踪打开文件的 space ("handles") 数量有限,因此根据 language/OS/whatever,您实际上可能会耗尽平台的文件句柄限制每个 thread/process/entire 系统。同样,解压通常也是一个文件一个文件地实现。
在 Java 中,您实际上可能正在使用 Zip 实用程序 class,读取每个文件,将其压缩到内存中的某个位置,然后关闭该文件,并循环查找其余文件;在整个过程结束时,将 Zip 文件保存到磁盘。
请参阅 ZipOutputStream 以了解您可以使用的 class。实际上,它的工作原理是接受一个 OutputStream(通过以写入模式打开文件创建),然后循环调用 putNextEntry、write、closeEntry,最后调用 close() 将文件刷新到磁盘。