微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

File.ReadLines(filePath).First() 是否立即关闭文件? 安全

如何解决File.ReadLines(filePath).First() 是否立即关闭文件? 安全

我知道在 IEnumerable 循环中使用 File.ReadLines() 返回的 foreach 时,文件会在循环后自动关闭。 我只需要快速检查文件的第一行。这足够了吗,还是会保持文件打开?

protected void Append(string filePath,Encoding encoding)
{
    try
    {
        string firstLine = File.ReadLines(filePath,encoding).First();
        // more code here
    }
    catch
    {
        // more code here
    }
}

解决方法

(请注意,这是针对返回 File.ReadLines()IEnumerable<String> - 这不适用于返回 File.ReadAllLines()String[]。)


File.ReadLines(filePath).First() 是否立即关闭文件?

是的

...假设“立即”是指当整个语句完成时 - 而不仅仅是内部的 ReadLines() 子表达式。


  • 在内部,File.ReadLines() 返回一个 instance of ReadLinesIterator - 这是一个 IEnumerable<T>
  • IEnumerable<T> 被迭代时,C#/.NET 使用 IEnumerable<T>.GetEnumerator<T>() 返回一个 IEnumerator<T>,它必须在程序完成迭代后被处理它想要什么。
    • 因为 IEnumerator<T> 实例必须被处理,所以我们总是鼓励您使用 foreach 为您处理此问题(而不是自己手动处理 IEnumerator<T>) .
      • foreach 还将确保 IEnumerator<T>foreach 循环体内抛出异常时被释放。
  • 在此特定情况下,ReadLinesIterator 包含一个 StreamReader(其中包含打开的 FileStream)。当 ReadLinesIterator 被释放时,内部 StreamReader 关闭,进而关闭 FileStream
  • .Frist() 方法是 Linq 的 Enumerable.First( IEnumerable<T> source )
    • 在内部,Linq 的 First() 与调用 foreach( T item in source ) 并立即在 foreach 内部返回相同 - 因此 First 方法将为您处理 ReadLinesIterator

安全

我注意到 ReadLinesIterator is both an IEnumerator<T> and an IEnumerable<T> 并且它包装了一个开放的 StreamReader - 这确实意味着您在使用 ReadLines() 时需要小心以确保 {{ 1}} 你看到的实际上是迭代的,否则你有泄漏打开文件句柄的风险。

...这也意味着,如果您使用的是 Linq 方法链并且在 Linq 链内部但在外部发生异常,则任何 Linq 的内部 IEnumerable<T>/{{1} }/try/catch 块,那么您将泄漏一个文件句柄,该句柄在 GC 完成 foreach 之前不会关闭......尽管我承认我很难想到什么时候会发生这种情况。

,

File.ReadLines 返回 IEnumerable<string>。 Enumerable 使用 IEnumerator<string> 读取行,这是一次性的。

阅读第一行并确保资源安全的正确方法:

var lines = File.ReadLines(path);
string firstLine;
using (var it = lines.GetEnumerator())
{
    if (!it.MoveNext())
        throw new InvalidOperationException("File is empty");
    firstLine = it.Current;
}

UseLine(firstLine);

虽然复杂,但绝对安全

,

使用流阅读器读取文件的最佳实践 ID。

var lines = new List<string>();

using (StreamReader reader = new StreamReader(@"C:\test.txt")) {
    var line = reader.ReadLine();

    while (line != null) {
        lines.Add(line);
        line = reader.ReadLine();
    }
}

一旦代码移出 using 语句,填充对象将被释放,wfile 将被关闭。 File.ReadLines 从不关闭文件。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。