2013-02-28 10 views
17

में निर्देशिका बनाना, एक ZipArchive ZipArchiveEntries का संग्रह है, और "प्रविष्टियां" को जोड़ना/निकालना अच्छी तरह से काम करता है। लेकिन ऐसा लगता है कि निर्देशिकाओं/नेस्टेड "अभिलेखागार" की कोई धारणा नहीं है। सिद्धांत रूप में, कक्षा को फ़ाइल सिस्टम से हटा दिया जाता है, जिसमें आप पूरी तरह मेमोरी स्ट्रीम में संग्रह बना सकते हैं। लेकिन अगर आप संग्रह में निर्देशिका संरचना जोड़ना चाहते हैं, तो आपको पथ के साथ एंट्री नाम उपसर्ग करना होगा।ZipArchive C# .Net 4.5

प्रश्न: निर्देशिका बनाने और प्रबंधित करने के लिए बेहतर इंटरफ़ेस बनाने के लिए आप ZipArchive को विस्तारित करने के बारे में कैसे जाएंगे?

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

इन पंक्तियों के साथ कुछ मेरे लिए अच्छे लगती है जबकि:

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

क्या आपका मतलब एक ज़िप के अंदर एक फ़ोल्डर संरचना, या ज़िपों का पदानुक्रम है? –

+0

एक ज़िप के अंदर फ़ोल्डर संरचना। –

उत्तर

27

आप दूसरे शब्दों में निम्नलिखित की तरह कुछ का उपयोग कर सकते है, हाथ से निर्देशिका संरचना बनाने के लिए:

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

उदाहरण के लिए, एक में एक फ़ाइल जोड़ने की वर्तमान पद्धति निर्देशिका पथ के साथ प्रविष्टि बनाने के लिए है

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); 
    } 
} 

और प्रयोग किया है::

यहाँ एक संभव समाधान है

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

लेकिन मैं घोंसले के साथ समस्याओं की भविष्यवाणी कर सकता हूं।

6

आप एक परियोजना है कि पूर्ण नेट का उपयोग कर सकते पर काम कर रहे हैं, तो आप उपयोग करने के लिए कोशिश कर सकते हैं explained here रूप ZipFile.CreateFromDirectory विधि,:

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); 
     } 
    } 
} 

बेशक यह केवल यदि आप एक दिया निर्देशिका के आधार पर नए ज़िप पैदा कर रहे काम करेंगे।

टिप्पणी के अनुसार, पिछला समाधान निर्देशिका संरचना को संरक्षित नहीं करता है। यदि इसकी आवश्यकता है, तो निम्न कोड यह संबोधित कर सकता है कि:

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

इस पर बस एक पैडेंटिक नोट, कुछ जो मुझे कुछ झुकाव के बाद मिला है। यह विंडोज़ डेस्कटॉप पर "बिल्कुल टू-> संपीड़ित फ़ाइल" मानक के रूप में * बिल्कुल * काम नहीं करता है। Windows SendTo संरचना में निर्देशिकाओं के लिए प्रविष्टियां स्पष्ट रूप से बनाएगा, जहां यह विधि निर्देशिका संरचना को अंतर्निहित रखती है, यानी यह निर्देशिकाओं के लिए प्रविष्टियां नहीं बनाती है, लेकिन निर्देशिका प्रत्येक फ़ाइल के पूर्ण पथ में सूचीबद्ध होती है। यह Winzip फ़ंक्शन काम करने के तरीके को बदलता नहीं है (यह किसी के साथ काम करने में प्रसन्नता है) लेकिन अगर आप एक विशिष्ट फ़ाइल संरचना की अपेक्षा कर रहे हैं तो यह केवल जागरूक होने की बात है। –

+0

धन्यवाद। मुझे बहुत समय बचाया। मैंने अभी कोड में एक छोटा सा संपादन किया है, उम्मीद है कि आप इसे स्वीकार करेंगे। मैंने ज़िप फ़ाइल ब्राउज़ करने योग्य बनाने के लिए, सापेक्ष पथ प्राप्त करने के लिए सबस्ट्रिंग (1) जोड़ा। –

0

सबफ़ोल्डर के साथ ज़िप फ़ोल्डर के पुनरावर्ती दृष्टिकोण का उपयोग करें।

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 + "/"); 
    } 
}