【问题标题】:Using a StreamWriter and StreamReader results in error "Stream not readable"使用 StreamWriter 和 StreamReader 会导致错误“流不可读”
【发布时间】:2014-09-15 09:45:05
【问题描述】:

我正在尝试将数据保存到 csv 文件,但想确保我要保存的数据尚未在 csv 文件中存在。因此,我想先读取文件,然后保存数据。

FileStream writer = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
FileStream reader = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

        using (StreamWriter sw = new StreamWriter(writer))
        {
            if (response.Datapoints.Count != 0)
            {
                foreach (var datapoint in response.Datapoints)
                {
                    sb = new StringBuilder();
                    toBeSaved = new string[] { nameSpace, metric, instanceId, datapoint.Timestamp.ToString()};

                    foreach (string str in toBeSaved)
                    {
                        if (str == toBeSaved.Last())
                        {
                            sb.Append(str);
                        }
                        else
                        {
                            sb.Append(str);
                            sb.Append(",");
                        }
                    }
                    // here I get the error that the "Stream is not Readable"
                    using (StreamReader sr = new StreamReader(reader))
                    {
                        if (sr.ReadLine() != sb.ToString())
                        { // only write the data if it is not already there in the file
                            sw.WriteLine(sb.ToString());
                        }
                    }
                }

【问题讨论】:

    标签: c# csv streamreader streamwriter


    【解决方案1】:

    这个 using 语句将处理 reader:

      using (StreamReader sr = new StreamReader(reader))
    

    StreamReader 的处置也将处置 reader。 当您在下一次循环迭代中访问它时,它会被释放,因此会出现错误消息。

    您可以通过在每次循环迭代时创建一个新的FileStream 读取器来规避此问题,或者通过重用StreamReader 并在循环后将其丢弃。

    我会使用不同的方法,这可能会更高效。

    除非你的输入文件真的很大,否则一开始就将它完全读入内存:

     var lines = File.ReadLines();
    

    然后在写入 csv 文件之前:

     if(!lines.Contains(sb.ToString())
        sw.WriteLine(sb.ToString());
    

    【讨论】:

    • 如果这是更好的选择,我如何重用 StreamReader?
    • 文件会随着我写入越来越多的数据而增长,可能会增长到以千兆字节为单位的大小。那么在开始时将整个文件读入内存是否仍然是一个好主意?
    • @BlackBruceWayne 如果它是千兆字节,那么这不是一个好主意。不幸的是,我无法告诉您如何修复您的代码,因为我认为您尝试查找重复项的方式存在概念上的问题。
    【解决方案2】:

    假设您使用的是 .Net 4.5 或更高版本,可以在 StreamReader 构造函数中设置它以保持流打开:

    http://msdn.microsoft.com/en-us/library/gg712952(v=vs.110).aspx

    public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen)
    

    【讨论】:

      猜你喜欢
      • 2013-12-17
      • 1970-01-01
      • 1970-01-01
      • 2011-04-23
      • 2014-06-17
      • 2012-02-22
      • 1970-01-01
      • 2015-09-17
      • 2011-05-26
      相关资源
      最近更新 更多