Groovy脚本压缩2GB以上文件报错‘Required array length too large’求助
解决Groovy打包大文件(超过2GB)到Zip时的"Required array length too large"错误
问题出在你用zipOutput << fileInputStream这行代码上——Groovy的<<操作符会尝试把整个文件的内容一次性读取到内存中的字节数组里。当文件大小超过2GB时,所需的数组长度会超过Java中int类型的最大值(2^31-1,约2.1GB),直接触发"Required array length too large"错误。
下面是修复后的代码,改用分块读写的方式处理文件,同时优化流的资源管理:
private ZipOutputStream addZipEntry(ZipOutputStream zipOutput, File file, String path) { if (file.isDirectory() && !path.endsWith('/')) { path += "/" } logger.info("zipfile: added $path") ZipEntry entry = new ZipEntry(path) entry.time = file.lastModified() zipOutput.putNextEntry(entry) if (file.isFile()) { // 用Groovy的withInputStream自动管理流,避免手动关闭遗漏 file.withInputStream { fis -> byte[] buffer = new byte[8192] // 8KB缓冲区,可根据性能需求调整大小 int bytesRead while ((bytesRead = fis.read(buffer)) != -1) { zipOutput.write(buffer, 0, bytesRead) } } } zipOutput.closeEntry() // 显式关闭当前Zip条目,确保资源正确释放 return zipOutput }
关键修改点:
- 替换
<<操作符为分块读写:通过固定大小的缓冲区循环读取文件内容,每次只加载一小部分数据到内存,从根本上避免了大数组的创建。 - 自动管理流资源:使用
file.withInputStream替代手动创建FileInputStream,Groovy会自动在代码块执行完毕后关闭流,避免资源泄漏。 - 显式关闭ZipEntry:添加
zipOutput.closeEntry(),确保每个压缩条目正确收尾,符合Zip文件的规范。
另外,Java 7及以上版本的ZipOutputStream默认支持Zip64格式,当文件大小超过4GB或条目数过多时会自动启用,所以2GB的文件用这种方式处理完全没问题。
内容的提问来源于stack exchange,提问作者omar ahmed
相关产品推荐
相关产品推荐

