0

我遇到了“无法从关闭的文本阅读器中读取”异常的问题。我有一个程序应该从文件中获取数据,然后用它做一些有趣的事情并获取所有内容的时间跨度。

首先在一个函数中,我正在加载数据:

IEnumerable<string> SomeVariable;
SomeVariable = (from _Something in File.ReadLines(@"file location") select _Something.Split(' ')[1] );

在第二个函数中,我运行了一次:

foreach (var _Something in SomeVariable)
{
    SomeList.Add(_Something);
}

在第三个函数中,当我尝试再次运行它时:

foreach (var _Something in SomeVariable)
{
    SomeOtherList.Add(_Something);
}

我得到异常:无法从关闭的文本阅读器中读取。看起来在一次枚举之后,不再可能遍历 SomeVariable。

这是 IEnumerable 本身的问题,还是与 File.ReadLines 函数有关?每次我想遍历它时,我都会发现从文件中重新加载数据非常愚蠢......

PS。我做了研究,我知道解决方案之一是将两个动作放在一个函数中,但不幸的是这是大学课程,我必须以这种方式编写它 - 我必须获得两个动作的不同时间跨度。

4

2 回答 2

4

尽管您已经有了解决方法:当您忘记Dispose()枚举器时,可能会发生这种情况,从而暗示程序中的其他地方存在错误。

这是一个简短的代码片段,它在第二个可靠地为我抛出异常foreach

var lines = File.ReadLines(@"<...>");
var enumerator = lines.GetEnumerator();
foreach (var line in lines) { }
foreach (var line in lines) { }

是的,如果您使用它File.ReadAllLines(...),并且如果您使用File.ReadLines(...).Select(...).ToList(). 但是,这不是一个完整的解决方案:异常的原因是enumeratorimplements IDisposable,但代码忘记处理它。

var lines = File.ReadLines(@"<...>");
using (var enumerator = lines.GetEnumerator()) { } // <--- using statement
foreach (var line in lines) { }
foreach (var line in lines) { }

您应该找出代码中发生的位置,并以类似方式修复它。该问题不在您显示的代码中。

您当然可以确保只读取文件一次。但是您应该将这一点与您遇到的异常分开考虑。

于 2013-05-18T15:48:12.607 回答
2

实际上,每次迭代SomeVariable可枚举时,您都在重新加载数据。LINQ 中的select子句对应于Enumerable.Select

该方法是通过使用延迟执行来实现的。立即返回值是一个存储执行操作所需的所有信息的对象。此方法表示的查询在使用枚举[例如]对象之前不会执行foreach

这可能不是您的预期行为;您希望您SomeVariable急切地填充结果字符串列表。为此,您可以简单地调用ToList您的可枚举:

IList<string> SomeVariable = 
(
    from _Something in File.ReadLines(@"file location") 
    select _Something.Split(' ')[1]
).ToList();
于 2013-05-18T15:12:10.130 回答