如何将 2 个 zip 文件合并为 1 个?

How can I merge 2 zip files into 1?

我有 2 个 zip 文件(zip1 和 zip2),我需要将这些文件合并为一个,我该如何解决? 我知道我可以修复它解压 ZIP1 到一个临时文件夹,然后将它添加到 zip2,但我认为它效率低下,更快的方法是什么?

我正在使用 System.IO.Compression 库...

我使用这段代码探索 Zip2:

 using (ZipArchive archive = ZipFile.OpenRead(Zip2))
 {
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
       /*...*/
    }
 }

PD/:Zip1 和 Zip2 文件有 个文件、文件夹和子文件夹

我还没有真正测试过这个,但你可以试一试:

    public ZipArchive Merge(List<ZipArchive> archives)
    {
        if (archives == null) throw new ArgumentNullException("archives");
        if (archives.Count == 1) return archives.Single();

        using (var memoryStream = new MemoryStream())
        {
            using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
            {
                foreach (var zipArchive in archives)
                {
                    foreach (var zipArchiveEntry in zipArchive.Entries)
                    {
                        var file = archive.CreateEntry(zipArchiveEntry.FullName);

                        using (var entryStream = file.Open()) {
                            using (var streamWriter = new StreamWriter(entryStream)) { streamWriter.Write(zipArchiveEntry.Open()); }
                        }
                    }
                }

                return archive;
            }
        }
    }

此示例说明如何在 DotNetZip 库的帮助下将两个 zip 文件合并到内存中的第三个文件或与实际文件合并:

//file1 and file2 are MemoryStream or file names
//for performance reason it is better that file1 is less than file2

//file1.Position = 0;//ensure at case of MemoryStream
using (var zip1 = ZipFile.Read(file1))
{
    //file2.Position = 0;//ensure at case of MemoryStream
    using (var zip2 = ZipFile.Read(file2))
    {
        var zip2EntryNames = zip2.Entries.Select(y => y.FileName).ToList();
        foreach (var entry in zip1.Entries.Where(x => !zip2EntryNames.Contains(x.FileName)).ToList())
        {
            var memoryStream = new MemoryStream();
            entry.Extract(memoryStream);
            memoryStream.Position = 0;
            zip2.AddEntry(entry.FileName, memoryStream);
        }
        if(save2file)
            zip2.Save(fileNameResult);
        else
            using (var result = new MemoryStream())
            {
                zip2.Save(result);                        
            }
    }
}

我遇到了同样的问题。 zip 文件作为字节数组来自另一个进程。此方法将它们的内容添加到现有的 ZipArchive。

using System.IO;
using System.IO.Compression;

        /// <summary>
        /// Copies the contents of a zip "file" represented as a byte array
        /// to the given ZipArchive.
        /// </summary>
        /// <param name="targetArchive">The archive to which to add the entries.</param>
        /// <param name="zippedSourceBuffer">The source data as zip "file" in a byte array.</param>
        public static void addZipBufferToZipArchive(ZipArchive targetArchive, byte[] zippedSourceBuffer)
        {
            using (MemoryStream zippedSourceStream = new MemoryStream(zippedSourceBuffer))
            {
                using (ZipArchive sourceArchive = new ZipArchive(zippedSourceStream))
                {
                    foreach (ZipArchiveEntry sourceEntry in sourceArchive.Entries)
                    {
                        ZipArchiveEntry targetEntry = targetArchive.CreateEntry(sourceEntry.FullName);
                        using (Stream targetEntryStream = targetEntry.Open())
                        {
                            using (Stream sourceStream = sourceEntry.Open())
                            {
                                sourceStream.CopyTo(targetEntryStream);
                            }
                        }
                    }
                }
            }
        }

似乎没有任何方法可以将 ZipArchiveEntry 从一个 ZipArchive 直接移动到另一个 ZipArchive,因此我求助于解压缩源并通过复制操作将其重新打包到目标。

如果您已经将 ZipArchive 作为源,则不需要 MemoryStream zippedSourceStream 并且可以修改代码以直接使用 sourceArchive 作为方法参数。