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

C#控制台应用ZIP分块合并报‘Unexpected end of archive’错误

ZIP分块拼接报错“Unexpected end of archive”修复方案

核心根因

  • ZIP流未完成完整写入就启动拆分:ZipArchive处于Create模式时,仅在实例执行Dispose(即离开using(zipArchive)代码块)后,才会写入ZIP格式强制要求的中央目录、文件结束标记(EOCD)数据。原代码在zipArchive仍存活、未完成最终写入的阶段就重置流位置读取数据,拆分得到的分块本身就是残缺的ZIP片段,拼接后必然缺失ZIP结构的尾部校验标记。这也是普通文本文件拆分拼接正常、但ZIP会报错的核心原因——普通文本写入后即为完整结构,而ZIP的结构需要最终写入阶段的收尾数据才能合法。
  • 分块缓存无差别写入冗余数据:拆分时直接将固定100KB大小的buffer加入分块列表,未截取本次Read实际读取的字节长度。如果最后一块ZIP数据不足100KB,buffer中剩余的未填充字节会被一并加入分块,进一步破坏文件完整性。

修复后代码

修正后的CreateChunks分块方法

public List<byte[]> CreateChunks(string fileName, string txtFilePath)
{
    const int chunkSize = 100 * 1000; // 100KB
    var fileChunks = new List<byte[]>();

    using (var memoryStream = new MemoryStream())
    {
        // leaveOpen设为true:ZipArchive Dispose时不会连带关闭内部的memoryStream
        using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
        {
            zipArchive.CreateEntryFromFile(txtFilePath, fileName, CompressionLevel.Optimal);
        } // 离开该代码块时ZipArchive完成所有ZIP结构的写入

        // 待ZIP完全写入流后,再开始拆分逻辑
        memoryStream.Position = 0;
        var buffer = new byte[chunkSize];
        
        int readBytes;
        // 仅截取实际读取的有效字节生成分块
        while ((readBytes = memoryStream.Read(buffer, 0, buffer.Length)) > 0)
        {
            var validChunk = new byte[readBytes];
            Array.Copy(buffer, 0, validChunk, 0, readBytes);
            fileChunks.Add(validChunk);
        }
    }
    return fileChunks;
}

健壮性优化后的JoinChunks拼接方法

原方法逻辑可正常工作,优化后可避免资源泄漏、路径拼接异常问题:

public void JoinChunks(List<byte[]> fileChunks, string outputDirectory)
{
    // 使用Path.Combine拼接路径,避免硬编码斜杠导致的跨平台路径异常
    string outputZipPath = Path.Combine(outputDirectory, "temp.zip");

    using (var memoryStream = new MemoryStream())
    using (var fileStream = new FileStream(outputZipPath, FileMode.Create))
    {
        foreach (var chunk in fileChunks)
        {
            memoryStream.Write(chunk, 0, chunk.Length);
        }
        memoryStream.WriteTo(fileStream);
    }
}

修复验证点

  • 拆分逻辑执行时机调整到ZipArchive完全Dispose之后,确保拆分的是包含完整EOCD标记的合法ZIP流
  • 每个分块仅包含实际读取的有效字节,无冗余数据
  • 拼接后得到的ZIP文件结构完整,可正常解压,不会触发“Unexpected end of archive”报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 18:54:03