【问题标题】:Unzipping a file from Base64 to string using DotNetZip使用 DotNetZip 将文件从 Base64 解压缩为字符串
【发布时间】:2014-04-11 09:34:48
【问题描述】:

当我尝试在代码中解压缩文件时,出现以下错误。

   at System.IO.StreamReader..ctor(Stream stream, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean leaveOpen)
   at System.IO.StreamReader..ctor(Stream stream)
   at Arkle.AzureServiceBusSample.MessageFetcher.ConvertBase64ZippedStringToNormalString(String stringBase64Zipped) in c:\CodeTfsArklePosBenLenovo\Arkle.AzureServiceBusSample\Arkle.AzureServiceBusSample\MessageFetcher.cs:line 171
   at Arkle.AzureServiceBusSample.MessageFetcher.DownloadMessages(String username, String password, String identifier) in c:\CodeTfsArklePosBenLenovo\Arkle.AzureServiceBusSample\Arkle.AzureServiceBusSample\MessageFetcher.cs:line 92
   at Arkle.AzureServiceBusSample.MessageFetcher.ReceiveMessages(String username, String password, String endPoint, String subscriptionName) in c:\CodeTfsArklePosBenLenovo\Arkle.AzureServiceBusSample\Arkle.AzureServiceBusSample\MessageFetcher.cs:line 48

System.ArgumentException:流不可读。 在 System.IO.StreamReader..ctor(流流,编码编码,布尔 detectEncodingFromByteOrderMarks, |nt32 bufferSize, Boolean |eaveOpen) 在 System.IO.StreamReader..ctor(Stream 流)

它发生在var streamReader1 = new StreamReader(ms); 行上,我已经检查过了,我能够将文件保存到磁盘并正确解压缩。但是我需要将它直接解压缩到内存流中。

我使用的是 DotNetZip 1.9.2 版。

我的代码:

    using ionic.zip;

    .............
    public static string UnzipToString(string stringBase64Zipped)
    {
        var bytesZipFile = Convert.FromBase64String(stringBase64Zipped);

        var msZipFile = new MemoryStream(bytesZipFile);
        msZipFile.Position = 0;
        using (var zipFile1 = ZipFile.Read(msZipFile))
        {
            zipFile1.Save(string.Format(@"C:\Temp\{0}.zip", Guid.NewGuid()));  // This works
            var zipEntry1 = zipFile1.Entries.First();

            using (var ms = new MemoryStream())
            {
                ms.Position = 0;
                zipEntry1.Extract(ms);
                var streamReader1 = new StreamReader(ms);
                var result = String.Empty;
                ms.Position = 0;
                result = streamReader1.ReadToEnd();

                return result;
            }
        }
    }

当我尝试按照以下建议将 memeorystream 位置设置为 0 时,我现在遇到了一个新错误。

System.ObjectDisposedException: Cannot access a closed Stream.

   at System.IO.__Error.StreamIsClosed()

   at System.IO.MemoryStream.set_Position(Int64 value)

   at Arkle.AzureServiceBusSample.MessageFetcher.ConvertBase64ZippedStringToNormalString(String stringBase64Zipped) in c:\CodeTfsArklePosBenLenovo\Arkle.AzureServiceBusSample\Arkle.AzureServiceBusSample\MessageFetcher.cs:line 171

   at Arkle.AzureServiceBusSample.MessageFetcher.DownloadMessages(String username, String password, String identifier) in c:\CodeTfsArklePosBenLenovo\Arkle.AzureServiceBusSample\Arkle.AzureServiceBusSample\MessageFetcher.cs:line 92

   at Arkle.AzureServiceBusSample.MessageFetcher.ReceiveMessages(String username, String password, String endPoint, String subscriptionName) in c:\CodeTfsArklePosBenLenovo\Arkle.AzureServiceBusSample\Arkle.AzureServiceBusSample\MessageFetcher.cs:line 48

【问题讨论】:

  • 将您的错误消息更改为文本而不是图像 LAZY!
  • 真的,你甚至会犯错误,而使用答案 =D ms.Position 只能在 之后设置(在这种情况下,在 @987654327 之后) @)。

标签: c# streamreader memorystream


【解决方案1】:

不确定您要归档什么。这是我的示例代码,它可以工作

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            var bytes = File.ReadAllBytes(@"e:\scripts_04-10-2014.zip");
            var zipAsBase64 = Convert.ToBase64String(bytes);

            foreach (var item in GetUnzippedItemsAsStream(zipAsBase64))
            {
                using (var fs = new FileStream(Path.Combine(@"e:\", item.Item1), FileMode.CreateNew,
                        FileAccess.ReadWrite))
                {
                    item.Item2.CopyTo(fs);
                }
            }
        }

        public IEnumerable<Tuple<string, Stream>> GetUnzippedItemsAsStream(string stringBase64Zipped)
        {
            var bytesZipFile = Convert.FromBase64String(stringBase64Zipped);
            using (var ms = new MemoryStream(bytesZipFile))
            {
                using (var zipFile = ZipFile.Read(ms))
                {
                    foreach (var zipEntry in zipFile.Entries)
                    {
                        var outputStream = new MemoryStream();
                            zipEntry.Extract(outputStream);
                            yield return new Tuple<string, Stream>(zipEntry.FileName, new MemoryStream(outputStream.ToArray()));
                    }
                }
            }
        }

请注意以下代码

  zipEntry.Extract(outputStream);
  yield return new Tuple<string, Stream>(zipEntry.FileName, new MemoryStream(outputStream.ToArray()));

我需要使用 old.ToArray() (which works even with closed MemoryStreams) 创建新的 MemoryStream,因为当前 DotNetZipLib 中有一个 known issue 用于在提取后关闭流。

【讨论】:

    【解决方案2】:
    zipEntry1.Extract(ms);
    ms.Position = 0;
    var streamReader1 = new StreamReader(ms);
    

    将 MemoryStream 位置重置为流的开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-12
      • 1970-01-01
      相关资源
      最近更新 更多