【问题标题】:Using Enumerable method with yield keyword and MemoryStream [duplicate]使用带有 yield 关键字和 MemoryStream 的 Enumerable 方法 [重复]
【发布时间】:2021-09-25 09:26:06
【问题描述】:

我写了下面的代码,它有效:

//VERSION 1;
static IEnumerable<string> ReadAsLines(string filename)
{
    using (StreamReader reader = new StreamReader(filename))
    {
        while (!reader.EndOfStream)
            yield return reader.ReadLine();
    }
}

使用上述方法:

const string fileData = @"path\to\somePipeDelimitedData.txt";
var reader = ReadAsLines(fileData); 
var headerArr = reader.First().Split('|');
foreach (var column in headerArr)
{
    var dummy = column;
}
var recordsEnumerable = reader.Skip(1); //skip first header Line
//Read other lines...
foreach (var record in recordsEnumerable)
{
    //read each line
    var rowArray = record.Split('|');
    //etc...
}

现在假设我从 Stream 而不是文件开始; 我尝试重写上面的代码,但我正在努力关闭流。 如何修复以下版本?

//VERSION 2;
static IEnumerable<string> ReadAsLines(Stream stream)
{
    using (StreamReader reader = new StreamReader(stream))
    {
        while (!reader.EndOfStream)
            yield return reader.ReadLine();
    }
}

调用版本 2:

byte[] dataByteArr = File.ReadAllBytes(fileData);
MemoryStream memStr = new MemoryStream(dataByteArr);

var reader2 = ReadAsLines(memStr);
var headerArr2 = reader2.First().Split('|'); //*** STREAM gets closed after this line
foreach (var column in headerArr2)
{
    var dummy = column;
}

var recordsEnumerable2 = reader2.Skip(1); //skip first header Line

//Read other lines... *** ERROR OCCURS HERE, as the Stream is closed.
foreach (var record in recordsEnumerable2)
{
    //read each line
    var rowArray = record.Split('|');
    //etc...
}

【问题讨论】:

  • @Progman 这不是这个问题的重复...He is asking why reader2.First() is causing dispose
  • @Selvin 没错,我知道流即将关闭,我的问题是为什么,以及如何使用 yield 关键字重新组织我的示例,以便它可以与 Stream 一起使用。
  • “我的问题是为什么” - 这不会出现在您的问题中的任何地方。这是因为您正在调用reader2.First(),它将释放为调用它的枚举创建的迭代器。
  • 你可以尝试只迭代一次......如果它是第一行,则标记指向它
  • 感谢大家对我找到解决方案的提示。

标签: c# ienumerable yield-return


【解决方案1】:

我重新组织了我最初的尝试,将 StreamReader 从 Enumerable 方法中拉出,并在我真正完成后将其丢弃。

byte[] dataByteArr = File.ReadAllBytes(fileData); //decoded bytes
var memStr = new MemoryStream(dataByteArr);

using (StreamReader sr = new StreamReader(memStr))
{
    var dataAsEnumerable = ReadAsLines(sr, memStr);
    var headerArr2 = dataAsEnumerable.First().Split('|'); 
    //*** HA! stream is still open !
    foreach (var column in headerArr2)
    {
        var dummy = column;
    }
    var dataMinusHeader = dataAsEnumerable.Skip(1);

    //Read other lines...
    foreach (var record in dataMinusHeader)
    {
        //read each line
        var rowArray = record.Split('|');
        //etc...
    }
}

【讨论】:

    猜你喜欢
    • 2013-03-18
    • 2019-07-06
    • 2018-12-20
    • 2011-11-02
    • 2011-05-11
    • 2017-04-10
    • 2012-07-01
    • 2018-06-17
    • 1970-01-01
    相关资源
    最近更新 更多