Questo codice:errore nel metodo file.readlines (..) di .NET Framework 4.0
IEnumerable<string> lines = File.ReadLines("file path");
foreach (var line in lines)
{
Console.WriteLine(line);
}
foreach (var line in lines)
{
Console.WriteLine(line);
}
genera ObjectDisposedException : {"Cannot read from a closed TextReader."}
se il secondo foreach
viene eseguita. Sembra che l'oggetto iteratore restituito da File.ReadLines(..)
non possa essere enumerato più di una volta. È necessario ottenere un nuovo oggetto iteratore chiamando File.ReadLines(..)
e quindi utilizzarlo per iterare.
Se sostituisco File.ReadLines(..)
con la mia versione (parametri non sono verificate, è solo un esempio):
public static IEnumerable<string> MyReadLines(string path)
{
using (var stream = new TextReader(path))
{
string line;
while ((line = stream.ReadLine()) != null)
{
yield return line;
}
}
}
è possibile scorrere più di una volta le righe del file.
Un'indagine che utilizza .Net Reflector
ha mostrato che l'implementazione dello File.ReadLines(..)
chiama un privato File.InternalReadLines(TextReader reader)
che crea l'iteratore effettivo. Il lettore ha passato come parametro viene utilizzato nel metodo MoveNext()
dell'iteratore per ottenere le linee del file e viene eliminato quando raggiungiamo la fine del file. Ciò significa che una volta che MoveNext()
restituisce false, non c'è modo di ripetere una seconda volta perché il lettore è chiuso e devi ottenere un nuovo lettore creando un nuovo iteratore con il metodo ReadLines(..)
.Nella mia versione viene creato un nuovo lettore nello MoveNext()
metodo ogni volta che iniziamo una nuova iterazione.
È questo il comportamento previsto del metodo File.ReadLines(..)
?
Trovo problematico il fatto che sia necessario chiamare il metodo ogni volta prima di enumerare i risultati. Dovresti anche chiamare il metodo ogni volta prima di iterare i risultati di una query Linq che utilizza il metodo.
_ "È questo il comportamento previsto del metodo File.ReadLines (..)?" _ Sì. Se hai consumato un 'StreamReader', sarà eliminato. Non c'è modo di andare avanti e indietro. Se ti serve devi usare 'File.ReadAllLines'. –
In realtà, una soluzione semplice come 'IEnumerable ReadLinesFixed (percorso stringa) {foreach (riga var in File.ReadLines (percorso)) restituisce una riga di ritorno; } 'funziona anche. –
Vlad