如何将文件解压缩到.NET内存流?

时间:2014-03-24 09:04:43

标签: c# .net ftp

我有文件(来自第三方)正在FTP到我们服务器上的目录。我下载它们并处理它们甚至'x'分钟。效果很好。

现在,有些文件是.zip个文件。这意味着我无法处理它们。我需要先解压缩它们。

FTP没有zip / unzipping的概念 - 所以我需要抓取zip文件,解压缩然后处理它。

查看MSDN zip api,我似乎无法解压缩到内存流?

这是唯一的方法......

  1. 解压缩到一个文件(什么目录?需要一些非常临时的位置......)
  2. 阅读文件内容
  3. 删除文件。
  4. 注意:文件的内容很小 - 例如4k< - > 1000K。

6 个答案:

答案 0 :(得分:58)

Zip压缩支持内置于:

using System.IO;
using System.IO.Compression;
// ^^^ requires a reference to System.IO.Compression.dll
static class Program
{
    const string path = ...
    static void Main()
    {
        using(var file = File.OpenRead(path))
        using(var zip = new ZipArchive(file, ZipArchiveMode.Read))
        {
            foreach(var entry in zip.Entries)
            {
                using(var stream = entry.Open())
                {
                    // do whatever we want with stream
                    // ...
                }
            }
        }
    }
}

通常你应该避免将其复制到另一个流中 - 只需“按原样”使用它,但是,如果你在MemoryStream绝对需要,你可以这样做:

using(var ms = new MemoryStream())
{
    stream.CopyTo(ms);
    ms.Position = 0; // rewind
    // do something with ms
}

答案 1 :(得分:8)

您可以使用ZipArchiveEntry.Open来获取信息流。

此代码假定zip存档有一个文本文件。

using (FileStream fs = new FileStream(path, FileMode.Open))
using (ZipArchive zip = new ZipArchive(fs) )
{
    var entry = zip.Entries.First();

    using (StreamReader sr = new StreamReader(entry.Open()))
    {
        Console.WriteLine(sr.ReadToEnd());
    }
}

答案 2 :(得分:5)

看起来这就是你需要的:

   using (var za = ZipFile.OpenRead(path))
   {
       foreach (var entry in sa.Entries)
       {
                using (var r = new StreamReader(entry.Open()))
                {
                    //your code here
                }
       }
   }

答案 3 :(得分:4)

  using (ZipArchive archive = new ZipArchive(webResponse.GetResponseStream()))
      {
      foreach (ZipArchiveEntry entry in archive.Entries)
          {
          Stream s = entry.Open();
          var sr = new StreamReader(s);
          var myStr = sr.ReadToEnd();
          }
      } 

答案 4 :(得分:0)

好吧,结合以上所有内容,假设您想以一种非常简单的方式获取一个名为 “ file.zip”并将其解压缩到“ C:\ temp”文件夹。 (注意:此示例仅针对压缩文本文件进行了测试)您可能需要对二进制文件进行一些修改。

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

        static void Main(string[] args)
        {
            //Call it like this:
            Unzip("file.zip",@"C:\temp");
        }

        static void Unzip(string sourceZip, string targetPath)
        {
            using (var z = ZipFile.OpenRead(sourceZip))
            {
                foreach (var entry in z.Entries)
                {                    
                    using (var r = new StreamReader(entry.Open()))
                    {
                        string uncompressedFile = Path.Combine(targetPath, entry.Name);
                        File.WriteAllText(uncompressedFile,r.ReadToEnd());
                    }
                }
            }

        }

答案 5 :(得分:-1)

您可以在各种其他库中使用SharpZipLib来实现此目的。

您可以使用以下代码示例解压缩到MemoryStreamas shown on their wiki

using ICSharpCode.SharpZipLib.Zip;

// Compresses the supplied memory stream, naming it as zipEntryName, into a zip,
// which is returned as a memory stream or a byte array.
//
public MemoryStream CreateToMemoryStream(MemoryStream memStreamIn, string zipEntryName) {

    MemoryStream outputMemStream = new MemoryStream();
    ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);

    zipStream.SetLevel(3); //0-9, 9 being the highest level of compression

    ZipEntry newEntry = new ZipEntry(zipEntryName);
    newEntry.DateTime = DateTime.Now;

    zipStream.PutNextEntry(newEntry);

    StreamUtils.Copy(memStreamIn, zipStream, new byte[4096]);
    zipStream.CloseEntry();

    zipStream.IsStreamOwner = false;    // False stops the Close also Closing the underlying stream.
    zipStream.Close();          // Must finish the ZipOutputStream before using outputMemStream.

    outputMemStream.Position = 0;
    return outputMemStream;

    // Alternative outputs:
    // ToArray is the cleaner and easiest to use correctly with the penalty of duplicating allocated memory.
    byte[] byteArrayOut = outputMemStream.ToArray();

    // GetBuffer returns a raw buffer raw and so you need to account for the true length yourself.
    byte[] byteArrayOut = outputMemStream.GetBuffer();
    long len = outputMemStream.Length;
}