Sé que cuando uso el IEnumerable devuelto por File.ReadLines() en un ciclo foreach , el archivo se cierra automáticamente después del ciclo. Solo necesito verificar rápidamente la primera línea de un archivo. ¿Es esto suficiente o mantendrá el archivo abierto?
protected void Append(string filePath, Encoding encoding) { try { string firstLine = File.ReadLines(filePath, encoding).First(); // more code here } catch { // more code here } }(Tenga en cuenta que esto es para File.ReadLines() que devuelve un IEnumerable<String> ; esto no es para File.ReadAllLines() que devuelve un String[] ).
¿
File.ReadLines(filePath).First()cierra el archivo inmediatamente?
... suponiendo que "inmediatamente" quiere decir cuando se completa la declaración completa, no solo la subexpresión interna ReadLines() .
File.ReadLines() devuelve una instancia de ReadLinesIterator , que es un IEnumerable<T> .IEnumerable<T> , C#/.NET usa IEnumerable<T>.GetEnumerator<T>() que devuelve un IEnumerator<T> que debe desecharse después de que el programa haya terminado de iterar lo que desea.IEnumerator<T> deben eliminarse, siempre se le recomienda usar foreach , que maneja esto por usted (en lugar de manejar manualmente un IEnumerator<T> usted mismo).foreach también garantizará que IEnumerator<T> se elimine si se lanza una excepción dentro del cuerpo del bucle foreach .ReadLinesIterator contiene un StreamReader (que contiene el FileStream abierto). Cuando se desecha ReadLinesIterator , se cierra el StreamReader interno, que a su vez cierra FileStream ..Frist() es Enumerable.First( IEnumerable<T> source ) de Linq.First() de Linq hace lo mismo que llamar a foreach( T item in source ) y regresar inmediatamente dentro de foreach, por lo que el método First eliminará ReadLinesIterator por usted. Observo que ReadLinesIterator es tanto un IEnumerator<T> como un IEnumerable<T> y envuelve un StreamReader abierto, lo que significa que debe tener cuidado al usar ReadLines() para asegurarse de que el IEnumerable<T> que ve es en realidad iterado, de lo contrario corre el riesgo de filtrar identificadores de archivos abiertos.
... esto también significa que si está utilizando una cadena de método Linq y ocurre una excepción dentro de la cadena Linq pero fuera de cualquiera de los bloques internos try/catch / foreach / using de Linq, perderá un identificador de archivo que no será cerrado hasta que GC finalice ReadLinesIterator ... aunque admito que me cuesta pensar cuándo podría suceder esto.
File.ReadLines devuelve IEnumerable<string> . Enumerable usa IEnumerator<string> para leer líneas, que es desechable.
Manera correcta de leer la primera línea y ser seguro con los recursos:
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);Es complicado pero seguro seguro
Identificación de mejores prácticas para leer el archivo usando el lector de flujo.
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(); } }Una vez que el código sale de la declaración de uso, se eliminará el objeto de relleno y se cerrará wfile. File.ReadLines nunca cierra el archivo.