简体   繁体   English

如何从byte [],到MemoryStream,Unzip,然后写入FileStream

[英]How to go from byte[], to MemoryStream, Unzip, then write to FileStream

I am unsure what I am doing wrong. 我不确定我做错了什么。 The files that I create after grabbing a byte[] (which is emailAttachment.Body) and passing it to the method ExtractZipFile, converting it to MemoryStream and then unzipping it, returning it as a KeyValuePair and then Writing to a file using FileStream . 我在抓取byte[] (即emailAttachment.Body)并将其传递给方法ExtractZipFile后创建的文件,将其转换为MemoryStream然后解压缩,将其作为KeyValuePair返回,然后使用FileStream写入文件。

However when I go to open the new created files there is an error in opening them. 但是,当我打开新创建的文件时,打开它们时出错。 They are not able to be opened. 它们无法打开。

The below are in the same class 以下是同一类

using Ionic.Zip;

var extractedFiles = ExtractZipFile(emailAttachment.Body);

foreach (KeyValuePair<string, MemoryStream> extractedFile in extractedFiles)
{                               
    string FileName = extractedFile.Key;
    using (FileStream file = new FileStream(CurrentFileSystem + 
    FileName.FileFullPath(),FileMode.Create, System.IO.FileAccess.Write))
    {
        byte[] bytes = new byte[extractedFile.Value.Length];
        extractedFile.Value.Read(bytes, 0, (int) xtractedFile.Value.Length);
        file.Write(bytes,0,bytes.Length);
        extractedFile.Value.Close();
     }
}


private Dictionary<string, MemoryStream> ExtractZipFile(byte[] messagePart)
{
    Dictionary<string, MemoryStream> result = new Dictionary<string,MemoryStream>();
    MemoryStream data = new MemoryStream(messagePart);
    using (ZipFile zip = ZipFile.Read(data))
    {
        foreach (ZipEntry ent in zip)
        {
            MemoryStream memoryStream = new MemoryStream();
            ent.Extract(memoryStream);
            result.Add(ent.FileName,memoryStream);
        }   
    }
    return result;
}

Is there something I am missing? 有什么我想念的吗? I do not want to save the original zip file just the extracted Files from MemoryStream . 我不想保存原始zip文件只是从MemoryStream提取的文件。 What am I doing wrong? 我究竟做错了什么?

After writing to your MemoryStream, you're not setting the position back to 0: 写入MemoryStream后,您没有将位置设置回0:

MemoryStream memoryStream = new MemoryStream();
ent.Extract(memoryStream);
result.Add(ent.FileName,memoryStream);

Because of this, the stream position will be at the end when you try to read from it, and you'll read nothing. 因此,当您尝试从中读取时,流位置将在最后,并且您将不会读取任何内容。 Make sure to rewind it: 确保回放它:

memoryStream.Position = 0;

Also, you don't have to handle the copy manually. 此外,您不必手动处理副本。 Just let the CopyTo method take care of it: 只需让CopyTo方法来处理它:

extractedFile.Value.CopyTo(file);

I'd suggest that you clean up your use of MemoryStream in your code. 我建议您清理代码中对MemoryStream的使用。

I agree that calling memoryStream.Position = 0; 我同意调用memoryStream.Position = 0; will allow this code to work correctly, but it's an easy thing to miss when reading and writing memory streams. 将允许此代码正常工作,但在读取和写入内存流时很容易错过。

It's better to write code that avoids the bug. 编写避免错误的代码会更好。

Try this: 尝试这个:

private IEnumerable<(string Path, byte[] Content)> ExtractZipFile(byte[] messagePart)
{
    using (var data = new MemoryStream(messagePart))
    {
        using (var zipFile = ZipFile.Read(data))
        {
            foreach (var zipEntry in zipFile)
            {
                using (var memoryStream = new MemoryStream())
                {
                    zipEntry.Extract(memoryStream);
                    yield return (Path: zipEntry.FileName, Content: memoryStream.ToArray());
                }
            }
        }
    }
}

Then your calling code would look something like this: 然后你的调用代码看起来像这样:

foreach (var extractedFile in ExtractZipFile(emailAttachment.Body))
{
    File.WriteAllBytes(Path.Combine(CurrentFileSystem, extractedFile.Path.FileFullPath()), extractedFile.Content);
}

It's just a lot less code and a much better chance of avoiding bugs. 这只是代码少得多,避免错误的机会要大得多。 The number one predictor of bugs in code is the number of lines of code you write. 代码中错误的首要预测因素是您编写的代码行数。

Since I find it all a lot of code for a simple operation, here's my two cents. 因为我找到了很多简单操作的代码,所以这是我的两分钱。

using Ionic.Zip;

using (var s = new MemoryStream(emailAttachment.Body))
using (ZipFile zip = ZipFile.Read(s))
{
    foreach (ZipEntry ent in zip)
    {
        string path = Path.Combine(CurrentFileSystem, ent.FileName.FileFullPath())
        using (FileStream file = new FileStream(path, FileAccess.Write))
        {
            ent.Extract(file);
        }   
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM