【问题标题】:Memory stream closed?内存流关闭?
【发布时间】:2019-02-14 10:05:23
【问题描述】:

MemoryStream 没有到达 using 语句的末尾时是如何关闭的?

MusicDataStore musicData = MusicDataStore.TestData();
BinaryFormatter formatter = new BinaryFormatter();
using (MemoryStream memStream = new MemoryStream())
  {
      formatter.Serialize(memStream, musicData);

      using (StreamReader reader = new StreamReader(memStream))
      {
           memStream.Position = 0;
           Console.WriteLine(reader.ReadToEnd());
      }

      //deserialize
      memStream.Position = 0;
      MusicDataStore input = (MusicDataStore)formatter.Deserialize(memStream);

  }

我应该能够反序列化 memStream,但它无法读取,因为它已关闭。

当我尝试删除 StreamReader 块时,我可以成功反序列化 memStream。为什么? StreamReader 块中的 memStream 发生了什么?

【问题讨论】:

  • 旁注:除非您非常小心,否则对于大多数人来说,使用BinaryFormatter 通常不是一个好的选择。我从事序列化工作很多(说真的,很多)——而且我看到人们被BinaryFormatter 烧死的次数……太多了。如果您能够选择不同的序列化工具,我强烈建议您这样做。也很乐意就选项提供建议。
  • additional additional: StreamReader and ReadToEnd() on a binary payload ... 实际上不是一个有用的操作;只要您这样做只是为了检查是否写入了某些内容:很好-但是-永远不要尝试对string做任何事情:当您尝试将其阅读为string时,它已经无法修复,因为它不是文本数据

标签: c# serialization stream


【解决方案1】:

StreamReader 获得它所提供的 Stream 的所有权,并在释放它时将其关闭(大多数在其构造函数中采用另一个 IDisposable 类型的类型都会这样做)。

This StreamReader constructor 接受一个布尔值,表示在 StreamReader 作为其最后一个参数后是否保持流打开:

using (var reader = new StreamReader(memStream, Encoding.UTF8, true, 1024, true))
{
    ...
}

(其他参数是StreamReader(Stream) 使用的默认值,来自the referencesource。)

正如 Marc Gravell 在 cmets 中正确指出的那样,我们已经说过要使用 UTF-8 编码,但看起来您的流是二进制的,绝对不是 UTF-8 文本!所以预计这在实践中会失败。查看BitConverter.ToString(memStream.GetBuffer(), 0, memStream.Length) 的输出可能更有用(或更简单但效率较低的BitConverter.ToString(memStream.ToArray()))。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    • 2010-09-25
    • 1970-01-01
    相关资源
    最近更新 更多