.net ZipArchive创建无效的ZIP文件

xoefb8l8  于 2023-11-20  发布在  .NET
关注(0)|答案(7)|浏览(151)

我正在尝试使用带有一个条目的代码创建一个新的ZIP包,并将ZIP包保存到一个文件中。我正在尝试使用System.IO.Compression.ZipArchive类来实现这一点。我正在使用以下代码创建ZIP包:

  1. using (MemoryStream zipStream = new MemoryStream())
  2. {
  3. using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create))
  4. {
  5. var entry = zip.CreateEntry("test.txt");
  6. using (StreamWriter sw = new StreamWriter(entry.Open()))
  7. {
  8. sw.WriteLine(
  9. "Etiam eros nunc, hendrerit nec malesuada vitae, pretium at ligula.");
  10. }

字符串
然后我保存ZIP到WinRT中的一个文件:

  1. var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("test.zip", CreationCollisionOption.ReplaceExisting);
  2. zipStream.Position = 0;
  3. using (Stream s = await file.OpenStreamForWriteAsync())
  4. {
  5. zipStream.CopyTo(s);
  6. }


或者在正常的.NET 4.5中:

  1. using (FileStream fs = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
  2. {
  3. zipStream.Position = 0;
  4. zipStream.CopyTo(fs);
  5. }


然而,我无法在Windows资源管理器,WinRAR等中打开生成的文件(我检查了生成的文件的大小与zipStream的长度匹配,因此流本身被正确保存到文件中。
是我做错了什么,还是ZipArchive类有问题?

qrjkbowd

qrjkbowd1#

在我的例子中,问题是当zip文件任务完成时,我没有处理**“zipArchive”**。即使我刷新并关闭了所有流。
所以,要么使用 * 使用 *,如上面的答案所建议的

  1. using (var zipArchive = new ZipArchive(File.OpenWrite("archive.zip"),
  2. ZipArchiveMode.Create))

字符串
或者在任务结束时处置变量.

  1. zipArchive.Dispose();

vjrehmav

vjrehmav2#

你可以遵循同样的想法,只是在相反的顺序,使用文件流像源.我做了下面的表格和文件被正常打开:

  1. string fileFormat = ".zip"; // any format
  2. string filename = "teste" + fileformat;
  3. StorageFile zipFile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(filename,CreationCollisionOption.ReplaceExisting);
  4. using (Stream zipStream = await zipFile.OpenStreamForWriteAsync()){
  5. using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create)){
  6. //Include your content here
  7. }
  8. }

字符串

cgfeq70w

cgfeq70w3#

完整的代码看起来像这样:

  1. var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("test.zip",CreationCollisionOption.ReplaceExisting);
  2. using (Stream zipStream = await zipFile.OpenStreamForWriteAsync())
  3. {
  4. using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
  5. {
  6. var entry = zip.CreateEntry("test.txt");
  7. using (StreamWriter sw = new StreamWriter(entry.Open()))
  8. {
  9. sw.WriteLine("Etiam eros nunc, hendrerit nec malesuada vitae, pretium at ligula.");
  10. }
  11. }
  12. }

字符串

j1dl9f46

j1dl9f464#

如果使用不带花括号的指令,请注意(C# >8.0):

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

字符串
使用带大括号的using语句,archive.Dispose将在作用域的末尾隐式调用。此外,由于您使用的是C# >8.0,我建议使用这种类型的异步实现,能够归档多个文件并被取消:

  1. static async Task<byte[]> CompressAsZipAsync(
  2. IAsyncEnumerable<(string FileName, Stream FileStream)> files,
  3. bool disposeStreamsAfterCompression = false,
  4. CancellationToken cancellationToken = default)
  5. {
  6. using var memoryStream = new MemoryStream();
  7. using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, false))
  8. {
  9. await foreach (var (FileName, FileStream) in files.WithCancellation(cancellationToken))
  10. {
  11. using var entryStream = archive.CreateEntry(FileName).Open();
  12. await FileStream.CopyToAsync(entryStream, cancellationToken);
  13. if (disposeStreamsAfterCompression)
  14. await FileStream.DisposeAsync();
  15. }
  16. }
  17. return memoryStream.ToArray();
  18. }

展开查看全部
3htmauhk

3htmauhk5#

我在代码中发现了一个--事后看来,很明显--错误。ZipArchive必须被处理才能将其内容写入其底层流。因此,我必须在ZipArchive的using块结束后将流保存到一个文件中。
并且,将其构造函数的leaveOpen参数设置为true很重要,以使其不会关闭底层流。因此,这里是完整的工作解决方案:

  1. using (MemoryStream zipStream = new MemoryStream())
  2. {
  3. using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
  4. {
  5. var entry = zip.CreateEntry("test.txt");
  6. using (StreamWriter sw = new StreamWriter(entry.Open()))
  7. {
  8. sw.WriteLine(
  9. "Etiam eros nunc, hendrerit nec malesuada vitae, pretium at ligula.");
  10. }
  11. }
  12. var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(
  13. "test.zip",
  14. CreationCollisionOption.ReplaceExisting);
  15. zipStream.Position = 0;
  16. using (Stream s = await file.OpenStreamForWriteAsync())
  17. {
  18. zipStream.CopyTo(s);
  19. }
  20. }

字符串

展开查看全部
uurity8g

uurity8g6#

  1. // Create file "archive.zip" in current directory use it as destination for ZIP archive
  2. using (var zipArchive = new ZipArchive(File.OpenWrite("archive.zip"),
  3. ZipArchiveMode.Create))
  4. {
  5. // Create entry inside ZIP archive with name "test.txt"
  6. using (var entry = zipArchive.CreateEntry("test.txt").Open())
  7. {
  8. // Copy content from current directory file "test.txt" into created ZIP entry
  9. using (var file = File.OpenRead("test.txt"))
  10. {
  11. file.CopyTo(entry);
  12. }
  13. }
  14. }

字符串
结果,您将获得存档“archive.zip“,其中包含单个条目文件“test.txt”。您需要此using级联,以避免与已处理的资源进行任何交互。

nfg76nw0

nfg76nw07#

在所有的流对象上,你必须从开始处倒回流,以便其他应用程序使用.Seek方法正确地读取它们。
范例:

  1. zipStream.Seek(0, SeekOrigin.Begin);

字符串

相关问题