【问题标题】:Writing a memory stream to a file将内存流写入文件
【发布时间】:2015-08-17 15:47:48
【问题描述】:

我尝试将 json 格式的数据作为字符串检索并将其写入文件,效果很好。现在我正在尝试使用 MemoryStream 做同样的事情,但没有任何内容写入文件 - 只是 [{},{},{},{},{}] 没有任何实际数据。

我的问题是 - 我如何检查数据是否确实正确进入内存流,或者问题是否发生在其他地方。我知道 myList 确实包含数据。

这是我的代码:

MemoryStream ms = new MemoryStream();
DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(List<myClass>));
dcjs.WriteObject(ms, myList);

using (FileStream fs = new FileStream(Path.Combine(Application.StartupPath,"MyFile.json"), FileMode.OpenOrCreate))
{
                ms.Position = 0;
                ms.Read(ms.ToArray(), 0, (int)ms.Length);
                fs.Write(ms.ToArray(), 0, ms.ToArray().Length);
                ms.Close();
                fs.Flush();
                fs.Close();
 }

【问题讨论】:

  • 并不是说这会解决您的问题,但可以考虑使用Stream.CopyTo Method 清理代码。
  • ms.Read(ms.ToArray(), 0, (int)ms.Length); 为什么要读取内存流,覆盖dcjs.WriteObject 放入的所有内容?这似乎是您的问题,不要重置流位置并自行改写。
  • 为什么要在 FileStream 之前写入 MemoryStream?但是使用 .net 4.0 你应该可以访问Stream.CopyTo(Stream)
  • 我尝试了 ms.CopyTo(fs) 但得到了相同的结果
  • @ElenaDBA 问题不在于您的文件写入。问题出在您的序列化程序中。

标签: c# json memorystream


【解决方案1】:

有一个很方便的方法,Stream.CopyTo(Stream)

using (MemoryStream ms = new MemoryStream())
{
    StreamWriter writer = new StreamWriter(ms);

    writer.WriteLine("asdasdasasdfasdasd");
    writer.Flush();

    //You have to rewind the MemoryStream before copying
    ms.Seek(0, SeekOrigin.Begin);

    using (FileStream fs = new FileStream("output.txt", FileMode.OpenOrCreate))
    {
        ms.CopyTo(fs);
        fs.Flush();
    }
}

另外,您不必关闭 fs,因为它在 using 语句中,并且将在最后处理。

【讨论】:

  • 什么也没发生——文件没有改变
  • 我更新了代码有一个修改,你需要使用Seek(0, SeekOrigin.Begin)
  • 我使用的是 .Net Framework 3.5,所以这可能与它有关,但我可以使用 Stream.CopyTo(Stream),因为它不存在。相反,我不得不使用Stream.WriteTo(Stream)
  • 您可以使用 ms.Position = 0 代替 ms.Seek(0, SeekOrigin.Begin) 来“倒回”流
  • 严格来说,fs.Flush() 是多余的,不是吗?因为文件流会在Close()d by Dispose() 时刷新? (我问是因为我有一个相关的错误,但我不敢相信在我打开文件流的所有地方添加Flush() 会解决任何问题)
【解决方案2】:
 using (var memoryStream = new MemoryStream())
 {
    ...

     var fileName = $"FileName.xlsx";
     string tempFilePath = Path.Combine(Path.GetTempPath() + fileName );
     using (var fs = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write))
     {
        memoryStream.WriteTo(fs);
     }

 }

【讨论】:

    【解决方案3】:

    //重置流的位置

    ms.Position = 0;
    

    //然后复制到文件流

    ms.CopyTo(fileStream);
    

    【讨论】:

    • 没有理由重置流位置,只需调用ms.ToArray() 就会将整个内存流(从零开始)复制到一个数组中。来自文档“将流内容写入字节数组,无论 Position 属性如何。”
    【解决方案4】:

    问题与您的文件流/内存流无关。问题是DataContractJsonSerializer 是一个 OPT IN 序列化程序。您需要将[DataMemberAttribute] 添加到您需要在myClass 上序列化的所有属性中。

    [DataContract]
    public class myClass
    {
         [DataMember]
         public string Foo { get; set; }
    }
    

    【讨论】:

      【解决方案5】:

      这行看起来有问题:

      ms.Read(ms.ToArray(), 0, (int)ms.Length);
      

      此时您不需要将任何内容读入内存流,尤其是当您编写代码以将 ms 读入 ms 时。

      我非常有信心,只需删除此行即可解决您的问题。

      【讨论】:

      • 在我尝试 ms.WriteTo(fs) 但结果相同之前
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      • 1970-01-01
      • 2011-11-04
      • 1970-01-01
      • 2012-06-13
      • 2016-03-24
      相关资源
      最近更新 更多