You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一Zip条目写入多数据后ByteArrayOutputStream大小未更新的问题

问题原因

ZipOutputStream内部自带缓冲区,写入的数据会先暂存到缓冲区中,不会立即同步到下层的ByteArrayOutputStream,这就是你看到outputStream.size()一直保持初始值的原因。另外,closeEntry()会终止当前Zip条目,之后无法再向同一个条目写入数据,这和你需要持续追加内容到abc.csv的需求冲突。

解决方案
  1. 实时刷新缓冲区:每次向ZipOutputStream写入数据后,调用flush()方法,将缓冲区的数据同步到ByteArrayOutputStream,这样就能正确获取已写入的字节大小。
  2. 优化资源管理:使用try-with-resources自动关闭流,避免手动关闭导致的资源泄漏。
  3. 调整流生命周期:确保ZipOutputStream在整个写入过程中保持打开状态,仅在所有数据处理完成后再关闭条目和流。
修改后的代码
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);

private void addToS3(List<Data> data) throws IOException {
    try {
        zipOutputStream.putNextEntry(new ZipEntry("abc.csv"));

        for (Data item : data) {
            // 使用try-with-resources自动管理流资源
            try (InputStream inputStream = new ByteArrayInputStream(item.getBytes());
                 InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
                 BufferedReader bufferedReader = new BufferedReader(reader)) {

                StringBuilder csvContent = new StringBuilder();
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    csvContent.append(line).append("\n");
                }

                // 写入数据后立即刷新缓冲区,同步到ByteArrayOutputStream
                zipOutputStream.write(csvContent.toString().getBytes(StandardCharsets.UTF_8));
                zipOutputStream.flush();

                // 检查当前已写入的字节大小,达到阈值则分片上传
                if (outputStream.size() > 5 * 1024 * 1024) {
                    uploadToS3ByPart(new ByteArrayInputStream(outputStream.toByteArray()), false);
                    outputStream.reset();
                }
            }
        }

        zipOutputStream.closeEntry();
    } finally {
        zipOutputStream.close();
    }

    // 上传剩余的最后一部分数据
    uploadToS3ByPart(new ByteArrayInputStream(outputStream.toByteArray()), true);
}
补充说明
  • 调用flush()只会将缓冲区的数据同步到下层流,不会终止当前Zip条目,因此可以继续向同一个abc.csv条目追加内容。
  • 分片上传时,outputStream.reset()会清空当前的字节数组,后续写入的数据会继续作为同一个Zip条目的内容,最终所有分片拼接后会形成完整的Zip文件,包含完整的abc.csv条目。
  • try-with-resources会自动关闭所有实现了AutoCloseable的资源,无需手动调用close(),避免了因忘记关闭流导致的资源泄漏问题。

内容的提问来源于stack exchange,提问作者Chandana MB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:32:55