You need to enable JavaScript to run this app. 如何通过SAF与DocumentFile正确解压含多级子目录的ZIP压缩包?
优惠活动
大模型
产品
解决方案
定价
更多

如何通过SAF与DocumentFile正确解压含多级子目录的ZIP压缩包?

基于SAF实现ZIP解压的问题说明

场景背景

使用存储访问框架(SAF)解压ZIP压缩包时,受框架限制无法使用任何File类对象,只能依靠ZipInputStream、ZipOutputStream与DocumentFile完成全部解压逻辑。
本次需要处理的ZIP包内置目录结构如下:

Folder 1/ABC 001.jpg
Folder 1/ABC 002.jpg
Folder 2/ABC 003.jpg
Folder 2/ABC 004.jpg
Folder 2/Folder 3/ABC 005.jpg
Folder 2/Folder 3/ABC 006.jpg
Folder 2/Folder 3/Folder 4/ABC 007.jpg
Folder 2/Folder 3/Folder 4/ABC 008.jpg
ABC 009.jpg

现有实现代码

public void extractZipFile(DocumentFile srcZipFile, DocumentFile destDir) throws IOException
{
    ZipEntry entry;

    InputStream inputStream = resolver.openInputStream(srcZipFile.getUri());

    try (java.util.zip.ZipInputStream zipInputStream = new java.util.zip.ZipInputStream(inputStream))
    {
        while ((entry = zipInputStream.getNextEntry()) != null)
        {
            DocumentFile currentDestDir = destDir;

            if (!entry.isDirectory())
            {
                unzipFile(entry, zipInputStream, currentDestDir);
            }
            else
            {
                String finalFolderName = entry.getName().replace("/", "");
                currentDestDir = destDir.createDirectory(finalFolderName);
            }
        }
    }

    inputStream.close();
}

private void unzipFile(ZipEntry fileEntry, java.util.zip.ZipInputStream zipInputStream, DocumentFile destDir) throws IOException
{
    int readLen;
    byte[] readBuffer = new byte[BUFFER_SIZE];

    DocumentFile destFile = destDir.createFile("*/*", fileEntry.getName());

    try (OutputStream outputStream = resolver.openOutputStream(destFile.getUri()))
    {
        while ((readLen = zipInputStream.read(readBuffer)) != -1)
        {
            outputStream.write(readBuffer, 0, readLen);
        }
    }
}

现存问题与偏差原因

按照上述代码执行后,解压输出的目录结构完全不符合预期,核心问题有两点:

  • 目录路径解析逻辑完全失效
    • 每次遍历ZipEntry时,currentDestDir 都被重置为根目标目录,没有沿ZIP内置路径逐级定位嵌套目录层级
    • 处理目录条目时,仅靠去掉字符串里的斜杠生成单层文件夹名,在根目录下创建独立文件夹,完全没有形成多层嵌套的目录结构
  • 文件写入逻辑路径错位
    • 处理普通文件条目时,直接将带全路径的entry.getName()作为文件名传入创建文件的方法,没有拆分路径片段、定位到对应层级的目标目录,导致所有文件直接落在根目录下,甚至因字符串包含斜杠出现命名异常

修正实现逻辑

不需要单独区分处理目录/文件条目,统一对每个ZipEntry的全路径做拆分,从根目标目录开始逐级匹配、创建层级目录,最后处理文件写入即可:

public void extractZipFile(DocumentFile srcZipFile, DocumentFile destDir) throws IOException
{
    ZipEntry entry;
    InputStream inputStream = resolver.openInputStream(srcZipFile.getUri());
    try (java.util.zip.ZipInputStream zipInputStream = new java.util.zip.ZipInputStream(inputStream))
    {
        while ((entry = zipInputStream.getNextEntry()) != null)
        {
            // 拆分全路径为各级片段
            String[] pathSegments = entry.getName().split("/");
            DocumentFile currentDir = destDir;
            // 遍历除最后一段外的所有路径片段,逐级定位/创建目录
            for (int i = 0; i < pathSegments.length - 1; i++) {
                String segment = pathSegments[i];
                if (segment.isEmpty()) continue;
                DocumentFile targetDir = currentDir.findFile(segment);
                if (targetDir == null || !targetDir.isDirectory()) {
                    targetDir = currentDir.createDirectory(segment);
                }
                currentDir = targetDir;
            }
            // 仅处理普通文件,跳过空的目录条目写入
            if (!entry.isDirectory()) {
                String fileName = pathSegments[pathSegments.length - 1];
                if (fileName.isEmpty()) continue;
                unzipFile(entry, zipInputStream, currentDir, fileName);
            }
        }
    }
    inputStream.close();
}

private void unzipFile(ZipEntry fileEntry, java.util.zip.ZipInputStream zipInputStream, DocumentFile destDir, String fileName) throws IOException
{
    int readLen;
    byte[] readBuffer = new byte[BUFFER_SIZE];
    DocumentFile destFile = destDir.createFile("*/*", fileName);
    try (OutputStream outputStream = resolver.openOutputStream(destFile.getUri()))
    {
        while ((readLen = zipInputStream.read(readBuffer)) != -1)
        {
            outputStream.write(readBuffer, 0, readLen);
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 09:27:02