c# 中 ZIP 文件的存档意外结束

问题描述 投票:0回答:2

我正在尝试压缩文本文件并将其拆分为控制台应用程序中的块(字节[])。

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

        using (var memoryStream = new MemoryStream())
        {
            using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, false))
            {
                zipArchive.CreateEntryFromFile($"{txtFilePath}", fileName, CompressionLevel.Optimal);

                memoryStream.Position = 0;

                var buffer = new byte[chunkSize];

                while (memoryStream.Read(buffer, 0, buffer.Length) > 0)
                {
                    fileChunks.Add(buffer);
                }
            }
        }
        return fileChunks;
    }

使用这些块,我尝试在另一个应用程序中创建一个 zip 文件。

    public void JoinChunks(List<byte[]> fileChunks, string filePath)
    {
        var memory = new MemoryStream();
        using (var file = new FileStream(filePath + "\\temp.zip", FileMode.Create))
        {
            foreach (var item in fileChunks)
            {
                memory.Write(item, 0, item.Length);
            }
            memory.WriteTo(file);
            file.Close();
        }
    }

查看创建的 zip 文件时,会弹出错误并显示“存档意外结束”。

如果我尝试对文本文件进行分块并将它们连接回来,那么它就可以正常工作。问题出在 ZIP 上。欢迎任何解决方案。

c# file memorystream c#-ziparchive
2个回答
2
投票

using (var memoryStream = new MemoryStream()) { using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, false)) { zipArchive.CreateEntryFromFile($"{txtFilePath}", fileName, CompressionLevel.Optimal); } memoryStream.Position = 0; var buffer = new byte[chunkSize]; while (memoryStream.Read(buffer, 0, buffer.Length) > 0) { fileChunks.Add(buffer); } }

即将非存档相关代码移出 
using

对象的

zipArchive
语句。
    


0
投票

static byte[] CompressAsZip(string fileName, Stream fileStram) { using var memoryStream = new MemoryStream(); using var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, false); using var entryStream = archive.CreateEntry(fileName).Open(); fileStram.CopyTo(entryStream); archive.Dispose(); //<- Necessary to close the archive correctly return memoryStream.ToArray(); }

使用带大括号的 using 语句,

archive.Dispose()

将在作用域结束时隐式调用。

另外,由于您使用的是 C# >8.0,我建议使用这种类型的异步实现,能够通过取消来归档多个文件:

static async Task<byte[]> CompressAsZipAsync( IAsyncEnumerable<(string FileName, Stream FileStream)> files, bool disposeStreamsAfterCompression = false, CancellationToken cancellationToken = default) { using var memoryStream = new MemoryStream(); using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, false)) { await foreach (var (FileName, FileStream) in files.WithCancellation(cancellationToken)) { using var entryStream = archive.CreateEntry(FileName).Open(); await FileStream.CopyToAsync(entryStream, cancellationToken); if (disposeStreamsAfterCompression) await FileStream.DisposeAsync(); } } return memoryStream.ToArray(); }

© www.soinside.com 2019 - 2024. All rights reserved.