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

如何不使用ByteArrayOutputStream从ZipEntry中获取字节并简化代码

回答

一、简化现有代码

你可以利用Java 9及以上版本提供的InputStream.readAllBytes()方法,直接读取ZipEntry对应的全部字节,省去手动循环写入ByteArrayOutputStream的步骤,代码会简洁很多:

public UnzippedFile unzip(ZipFile zipFile) throws IOException {
    var unzippedFile = new UnzippedFile();
    try (ZipInputStream zipInputStream = ZipUtils.toZipInputStream(zipFile)) {
        ZipEntry entry;
        while ((entry = zipInputStream.getNextEntry()) != null) {
            // 直接读取当前entry的全部字节
            byte[] entryBytes = zipInputStream.readAllBytes();
            unzippedFile.addFileToMap(entry.getName(), entryBytes);
            zipInputStream.closeEntry(); // 显式关闭entry,确保资源释放
        }
    }
    return unzippedFile;
}

如果你的环境是Java 8,也可以封装一个工具方法来替代readAllBytes(),避免重复写循环逻辑:

private static byte[] readAllBytes(InputStream in) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    while ((len = in.read(buffer)) != -1) {
        out.write(buffer, 0, len);
    }
    return out.toByteArray();
}

之后在主方法里调用这个工具方法,代码结构会更整洁。

二、不使用ByteArrayOutputStream的实现方式

除了上述readAllBytes()(JDK原生实现内部虽类似ByteArrayOutputStream逻辑,但上层无需显式编写),如果要完全手动实现不依赖它的逻辑,可以先获取ZipEntry的大小,预先分配对应长度的字节数组再读取:

public UnzippedFile unzip(ZipFile zipFile) throws IOException {
    var unzippedFile = new UnzippedFile();
    try (ZipInputStream zipInputStream = ZipUtils.toZipInputStream(zipFile)) {
        ZipEntry entry;
        while ((entry = zipInputStream.getNextEntry()) != null) {
            long entrySize = entry.getSize();
            if (entrySize == -1) {
                // 无法获取entry大小,降级到readAllBytes方式
                byte[] entryBytes = zipInputStream.readAllBytes();
                unzippedFile.addFileToMap(entry.getName(), entryBytes);
            } else {
                // 预先分配对应大小的字节数组
                byte[] entryBytes = new byte[(int) entrySize];
                int totalRead = 0;
                int readLen;
                while (totalRead < entrySize && (readLen = zipInputStream.read(entryBytes, totalRead, (int) entrySize - totalRead)) != -1) {
                    totalRead += readLen;
                }
                unzippedFile.addFileToMap(entry.getName(), entryBytes);
            }
            zipInputStream.closeEntry();
        }
    }
    return unzippedFile;
}

注意:entry.getSize()可能返回-1(比如压缩文件使用了无法预知压缩后大小的算法,或者entry是目录),这种情况需要做兼容处理,降级到通用读取方式。

另外,若使用第三方库如Apache Commons IO的IOUtils.toByteArray(InputStream),也能避免自己编写ByteArrayOutputStream相关逻辑,但这需要引入外部依赖,可根据项目需求选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:15:34