Как я могу разархивировать файл в поток памяти .NET?
У меня есть файлы (от третьих сторон), которые являются FTP'd в каталоге на нашем сервере. Я загружаю их и обрабатываю их даже "х" минут. Отлично работает.
Теперь некоторые файлы являются .zip
файлами. Это означает, что я не могу их обработать. Мне нужно сначала распаковать их.
FTP не имеет понятия об zip/unzipping - поэтому мне нужно захватить zip файл, разархивировать его, а затем обработать.
Глядя на MSDN zip api, похоже, что я не могу разархивировать в поток памяти?
Итак, единственный способ сделать это...
- Разархивируйте файл (в каком каталоге нужно какое-то место для размещения...)
- Прочитать содержимое файла
- Удалить файл.
ПРИМЕЧАНИЕ. Содержимое файла невелико - скажем, 4k ↔ 1000k.
Ответы
Ответ 1
Поддержка сжатия 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
}
Ответ 2
Вы можете использовать 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());
}
}
Ответ 3
Похоже, вот что вам нужно:
using (var za = ZipFile.OpenRead(path))
{
foreach (var entry in sa.Entries)
{
using (var r = new StreamReader(entry.Open()))
{
//your code here
}
}
}
Ответ 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();
}
}
Ответ 5
Вы можете использовать SharpZipLib среди множества других библиотек для достижения этой цели.
Вы можете использовать следующий пример кода, чтобы распаковать в MemoryStream
, как показано на их вики:
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;
}