Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is File.ReadAllLines lazy loaded when using with LINQ Where?

I would like to know if the following code is lazy evaluated or will crash in the way i handle possible exception of ReadAllLines(). I know for sure that Where clause is lazy evaluated but i'm not sure when i use it with ReadAllLines(). A possible explanation of how and why would be appreciated.

File.ReadAllLines Exceptions

var fileLines = File.ReadAllLines(filePath).Where(line =>
{
    line = line.Trim();
    return line.Contains("hello");
});

string search;
try
{
    search = fileLines.Single();
}
catch (Exception exception)
{
    ...log the exception...
}

Thanks in advance

like image 432
CodeArtist Avatar asked Dec 25 '22 04:12

CodeArtist


1 Answers

File.ReadAllLines is not lazy loaded, it loads all into memory.

string[]  allLines = File.ReadAllLines(filePath);

If you want to use LINQ's deferred execution you can use File.ReadLines instead:

var fileLines = File.ReadLines(filePath)
    .Where(line =>
    {
        line = line.Trim();
        return line.Contains("hello");
    });

This is also documented:

The ReadLines and ReadAllLines methods differ as follows: When you use ReadLines, you can start enumerating the collection of strings before the whole collection is returned; when you use ReadAllLines, you must wait for the whole array of strings be returned before you can access the array. Therefore, when you are working with very large files, ReadLines can be more efficient.

But note that you have to be careful with ReadLines since you cannot use it twice. If you try to "execute" it a second time you'll get an ObjectDisposedException since the underlying stream is already disposed. Update This bug seems to be fixed.

This will cause an exception for example:

var lines = File.ReadLines(path);
string header = lines.First();
string secondLine = lines.Skip(1).First();

You cannot use it either to write to the same file since the stream is still open.

File.WriteAllLines(path, File.ReadLines(path)); // exception:  being used by another process.

In these cases File.ReadAllLines is more appropriate.

like image 161
Tim Schmelter Avatar answered Dec 27 '22 18:12

Tim Schmelter