Comment puis-je décompresser un fichier pour a.NET flux de mémoire?

j'ai des fichiers (provenant de tiers) qui sont FTP vers un répertoire sur notre serveur. Je les télécharge et je les traite même en " x " minutes. Fonctionne très bien.

Maintenant, certains fichiers sont .zip fichiers. Ce qui veut dire que je ne peux pas les traiter. J'ai besoin de décompresser en premier.

FTP n'a aucun concept de zip/unzipping - donc je vais avoir besoin de saisir le fichier zip, décompresser, puis le traiter.

Regarder MSDN zip api, il semble y avoir aucun moyen que je peux décompresser pour un flux de mémoire?

Donc est la seule façon de le faire...

  1. décompresser vers un fichier (quel répertoire? besoin de quelques -très - temp emplacement ...)
  2. Lire le contenu du fichier
  3. Supprimer le fichier.

NOTE: Le contenu du fichier sont de petits - dire 4k 1000k.

24
demandé sur Pure.Krome 2014-03-24 13:04:43

5 réponses

le support de compression Zip est intégré dans:

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
                    // ...
                }
            }
        }
    }
}

Normalement, vous devriez éviter de le copier dans un autre jet - il suffit de l'utiliser "tel quel", cependant, si vous absolument besoin dans un MemoryStream, vous pouvez faire:

using(var ms = new MemoryStream())
{
    stream.CopyTo(ms);
    ms.Position = 0; // rewind
    // do something with ms
}
49
répondu Marc Gravell 2014-03-24 09:14:11

Vous pouvez utiliser ZipArchiveEntry.Open pour obtenir un flux de données.

ce code suppose que l'archive zip a un fichier texte.

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());
    }
}
7
répondu dcastro 2014-03-24 11:51:24

Ressemble ici est ce que vous avez besoin de:

   using (var za = ZipFile.OpenRead(path))
   {
       foreach (var entry in sa.Entries)
       {
                using (var r = new StreamReader(entry.Open()))
                {
                    //your code here
                }
       }
   }
5
répondu Uriil 2014-03-24 09:22:48
  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();
          }
      } 
3
répondu Zia Khan 2016-10-20 04:37:15

Vous pouvez utiliser SharpZipLib parmi une variété d'autres bibliothèques pour y parvenir.

Vous pouvez utiliser l'exemple de code suivant pour décompresser un MemoryStream,comme indiqué sur leur 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;
}
-1
répondu aevitas 2014-03-24 09:08:35