【问题标题】:How to go from byte[], to MemoryStream, Unzip, then write to FileStream如何从 byte[] 到 MemoryStream,解压缩,然后写入 FileStream
【发布时间】:2019-03-04 22:34:23
【问题描述】:

我不确定我做错了什么。我在获取byte[](即emailAttachment.Body)并将其传递给方法ExtractZipFile,将其转换为MemoryStream,然后解压缩,将其返回为KeyValuePair,然后写入文件后创建的文件使用FileStream

但是,当我打开新创建的文件时,打开它们时出错。它们无法打开。

以下属于同一类

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

我有什么遗漏吗?我不想只保存从MemoryStream 提取的文件的原始 zip 文件。 我做错了什么?

【问题讨论】:

  • This question's answer 似乎可以满足您的需求。很难说,因为你在那里添加了Dictionary
  • 首先你应该处理所有一次性用品。
  • 另外,不要做CurrentFileSystem + FileName.FileFullPath(),总是做System.IO.Path.Combine(CurrentFileSystem, FileName.FileFullPath())
  • 确保在写入后将 MemoryStream 的位置设置回 0,因为我怀疑 ent.Extract 会处理它
  • @KevinGosse 找到了它。旁注:Stream 有一个非常方便的CopyTo 方法。或者更方便,直接将ZipEntry解压到新创建的FileStream

标签: c# filestream zipfile memorystream


【解决方案1】:

写入 MemoryStream 后,您没有将位置设置回 0:

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

因此,当您尝试从中读取时,流位置将位于末尾,并且您什么也不会读取。确保倒带:

memoryStream.Position = 0;

此外,您不必手动处理副本。只需让CopyTo 方法处理它:

extractedFile.Value.CopyTo(file);

【讨论】:

  • 我自己不会找到这个解决方案。谢谢
【解决方案2】:

我建议您清理代码中对 MemoryStream 的使用。

我同意调用memoryStream.Position = 0; 将允许此代码正常工作,但在读写内存流时很容易错过。

最好编写避免错误的代码。

试试这个:

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

那么您的调用代码将如下所示:

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

这只是更少的代码和更好的避免错误的机会。代码中错误的第一预测指标是您编写的代码行数。

【讨论】:

  • 我很欣赏代码。我已经实施了。不幸的是,我是快速为我们公司工作的 2 名开发人员中的 1 名,我并不总是考虑代码的效率,只是一些可行的东西。我是内存流的新手,并在 stackoverflow 上寻找解决方案并使用它。我可能会尝试使用网站 CodeReview 来获得一些反馈。不过能得到一些反馈还是不错的。我学到了一些东西。
  • @DarrenWood - 尝试学习新的做事方法总是值得的 - 特别是如果它们有助于编写更少的错误代码。我唯一要提醒的是,您在网上找到的任何解决方案都应该在将其放入生产代码之前仔细检查。不要只是随便复制粘贴。
【解决方案3】:

因为我发现一个简单的操作有很多代码,这是我的两分钱。

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

【讨论】:

  • 代码量很大,我很高兴学到了一些关于效率的知识。谢谢你的回答
  • 甚至zip.ExtractAll(CurrentFileSystem) 可能真的有用吗?
  • 请注意,以编程方式从电子邮件附件中提取 zip 文件可能会导致重大安全风险...
猜你喜欢
  • 2015-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多