2013-02-28 39 views
17

Một ZipArchive là một bộ sưu tập của ZipArchiveEntries, và thêm/loại bỏ "Entries" hoạt động độc đáo. Nhưng nó xuất hiện không có khái niệm về thư mục/lồng nhau "Lưu trữ". Về lý thuyết, lớp được tách ra từ một hệ thống tệp, trong đó bạn có thể tạo tệp lưu trữ hoàn toàn trong luồng bộ nhớ. Nhưng nếu bạn muốn thêm một cấu trúc thư mục trong kho lưu trữ, bạn phải đặt trước tên mục nhập với một đường dẫn.Tạo thư mục trong một ZipArchive C# .Net 4.5

Câu hỏi: Bạn sẽ mở rộng ZipArchive như thế nào để tạo giao diện tốt hơn để tạo và quản lý thư mục?

Ví dụ, phương pháp hiện thêm một tập tin vào một thư mục là để tạo ra các mục với đường dẫn thư mục:

var entry = _archive.CreateEntry("directory/entryname"); 

trong khi một cái gì đó dọc theo những dòng dường như đẹp hơn với tôi:

var directory = _archive.CreateDirectoryEntry("directory"); 
var entry = _directory.CreateEntry("entryname"); 
+0

Bạn có nghĩa là cấu trúc thư mục bên trong một zip hoặc phân cấp các khóa không? –

+0

Cấu trúc thư mục bên trong một mã zip duy nhất. –

Trả lời

27

Bạn có thể sử dụng một cái gì đó như sau, nói cách khác, tạo cấu trúc thư mục bằng tay:

using (var fs = new FileStream("1.zip", FileMode.Create)) 
using (var zip = new ZipArchive(fs, ZipArchiveMode.Create)) 
{ 
    zip.CreateEntry("12/3/"); // just end with "/" 
} 
6

Đây là một giải pháp có thể có:

public static class ZipArchiveExtension 
{ 
    public static ZipArchiveDirectory CreateDirectory(this ZipArchive @this, string directoryPath) 
    { 
     return new ZipArchiveDirectory(@this, directoryPath); 
    } 
} 

public class ZipArchiveDirectory 
{ 
    private readonly string _directory; 
    private ZipArchive _archive; 

    internal ZipArchiveDirectory(ZipArchive archive, string directory) 
    { 
     _archive = archive; 
     _directory = directory; 
    } 

    public ZipArchive Archive { get{return _archive;}} 

    public ZipArchiveEntry CreateEntry(string entry) 
    { 
     return _archive.CreateEntry(_directory + "/" + entry); 
    } 

    public ZipArchiveEntry CreateEntry(string entry, CompressionLevel compressionLevel) 
    { 
     return _archive.CreateEntry(_directory + "/" + entry, compressionLevel); 
    } 
} 

và sử dụng:

var directory = _archive.CreateDirectory(context); 
var entry = directory.CreateEntry(context); 
var stream = entry.Open(); 

nhưng tôi có thể thấy trước các vấn đề với cách làm tổ, có lẽ.

6

Nếu bạn đang làm việc trên một dự án mà có thể sử dụng đầy đủ NET bạn có thể cố gắng sử dụng các phương pháp ZipFile.CreateFromDirectory, như explained here:

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

namespace ConsoleApplication 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string startPath = @"c:\example\start"; 
      string zipPath = @"c:\example\result.zip"; 
      string extractPath = @"c:\example\extract"; 

      ZipFile.CreateFromDirectory(startPath, zipPath, CompressionLevel.Fastest, true); 

      ZipFile.ExtractToDirectory(zipPath, extractPath); 
     } 
    } 
} 

Tất nhiên điều này sẽ chỉ làm việc nếu bạn đang tạo kéo khóa mới dựa trên một thư mục nhất định.

Theo nhận xét, giải pháp trước không giữ cấu trúc thư mục. Nếu cần, sau đó mã sau có thể giải quyết:

var InputDirectory = @"c:\example\start"; 
    var OutputFilename = @"c:\example\result.zip"; 
    using (Stream zipStream = new FileStream(Path.GetFullPath(OutputFilename), FileMode.Create, FileAccess.Write)) 
    using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create)) 
    { 
     foreach(var filePath in System.IO.Directory.GetFiles(InputDirectory,"*.*",System.IO.SearchOption.AllDirectories)) 
     { 
      var relativePath = filePath.Replace(InputDirectory,string.Empty); 
      using (Stream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) 
      using (Stream fileStreamInZip = archive.CreateEntry(relativePath).Open()) 
       fileStream.CopyTo(fileStreamInZip); 
     } 
    } 
+3

Chỉ là một lưu ý nhỏ về điều này, một điều tôi đã tìm thấy sau khi một số không quan trọng. Nó không hoạt động * chính xác * như một tiêu chuẩn "Sent To-> Nén tập tin" hiện trên một cửa sổ máy tính để bàn. Windows SendTo sẽ tạo các mục cho các thư mục trong cấu trúc một cách rõ ràng, khi mà phương thức này duy trì cấu trúc thư mục ngầm định, tức là nó không tạo các mục nhập cho các thư mục, nhưng các thư mục được liệt kê trong đường dẫn đầy đủ đến mỗi tệp. Nó không thay đổi cách hoạt động của hàm winzip (thật vui khi làm việc với một trong hai) nhưng nó chỉ là vấn đề được nhận biết nếu bạn đang mong đợi một cấu trúc tệp cụ thể. –

+0

Cảm ơn. Đã dành cho tôi rất nhiều thời gian. Tôi chỉ làm một chỉnh sửa nhỏ cho mã, hy vọng bạn chấp nhận nó. Tôi đã thêm chuỗi con (1) để nhận đường dẫn tương đối, để làm cho tệp zip có thể duyệt được. –

0

Sử dụng phương pháp đệ quy cho Thư mục Zip với Thư mục con.

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.IO.Compression; 

public static async Task<bool> ZipFileHelper(IFolder folderForZipping, IFolder folderForZipFile, string zipFileName) 
{ 
    if (folderForZipping == null || folderForZipFile == null 
     || string.IsNullOrEmpty(zipFileName)) 
    { 
     throw new ArgumentException("Invalid argument..."); 
    } 

    IFile zipFile = await folderForZipFile.CreateFileAsync(zipFileName, CreationCollisionOption.ReplaceExisting); 

    // Create zip archive to access compressed files in memory stream 
    using (MemoryStream zipStream = new MemoryStream()) 
    { 
     using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) 
     { 
      await ZipSubFolders(folderForZipping, zip, ""); 
     } 

     zipStream.Position = 0; 
     using (Stream s = await zipFile.OpenAsync(FileAccess.ReadAndWrite)) 
     { 
      zipStream.CopyTo(s); 
     } 
    } 
    return true; 
} 

//Create zip file entry for folder and subfolders("sub/1.txt") 
private static async Task ZipSubFolders(IFolder folder, ZipArchive zip, string dir) 
{ 
    if (folder == null || zip == null) 
     return; 

    var files = await folder.GetFilesAsync(); 
    var en = files.GetEnumerator(); 
    while (en.MoveNext()) 
    { 
     var file = en.Current; 
     var entry = zip.CreateEntryFromFile(file.Path, dir + file.Name);     
    } 

    var folders = await folder.GetFoldersAsync(); 
    var fEn = folders.GetEnumerator(); 
    while (fEn.MoveNext()) 
    { 
     await ZipSubFolders(fEn.Current, zip, dir + fEn.Current.Name + "/"); 
    } 
} 
Các vấn đề liên quan