2012-10-05 17 views
12

¿Cómo leo todas las líneas de un archivo de texto que también está abierto en Excel en string[] sin obtener la excepción IO?¿Cómo realizo File.ReadAllLines en un archivo que también está abierto en Excel?

No es esta cuestión que podría ser una parte de la respuesta, aunque no sé cómo podría utilizar lo que hay allí: How do I open an already opened file with a .net StreamReader?

+0

¿Qué no entiendo acerca de la respuesta a la que vinculó? Está bastante claro. ¿Lo has probado? Nos muestra tu código – Polyfun

+0

¿Qué debo hacer con ese código para rellenar mis 'cadenas [] líneas' con líneas de un archivo de texto? No hay nada al respecto allí. – user1306322

+0

http://stackoverflow.com/questions/3560651/whats-the-least-invasive-way-to-read-a-locked-file-in-c-sharp-perhaps-in-unsaf – m0s

Respuesta

30

Su problema es que Excel abre el archivo como de lectura/escritura. File.ReadAllLines() no puede acceder al archivo cuando está abierto para escribir en otra aplicación. Si abre la csv en Excel como de solo lectura, no encontrará esta excepción.

Esto se debe a que la implementación en .Net no abre la secuencia interna con los permisos adecuados para acceder al archivo cuando otra aplicación tiene permisos de escritura.

Así que la solución aquí es simple, escriba su propio método ReadAllLines() que establece los permisos apropiados al iniciar el Stream subyacente.

Aquí es una idea que se inspira en gran medida de lo que ReadAllLines() lo hace por su propia cuenta:

public string[] WriteSafeReadAllLines(String path) 
{ 
    using (var csv = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
    using (var sr = new StreamReader(csv)) 
    { 
     List<string> file = new List<string>(); 
     while (!sr.EndOfStream) 
     { 
      file.Add(sr.ReadLine()); 
     } 

     return file.ToArray(); 
    } 
} 

La única diferencia entre esto y lo ReadAllLines hace es el permiso FileShare se establece en FileShare.ReadWrite, lo que permite abrir el archivo incluso cuando está abierto con permisos de lectura/escritura en otra aplicación.

Ahora, debe comprender los problemas que pueden surgir de esto, ya que puede haber complicaciones ya que otra aplicación tiene permisos de escritura en el archivo.

  1. Usted va a estar leyendo la última versión guardada del archivo, por lo que si usted tiene cambios sin guardar en Excel, este método no les va a leer
  2. Si guarda el archivo en Excel, mientras que este método es en En el medio de leerlo, probablemente obtendrá una excepción según las circunstancias. Esto se debe a que el archivo está completamente bloqueado mientras se guarda, por lo que si intenta leer el archivo mientras está bloqueado, lanzará un System.IO.IOException.
  3. Y si guarda el archivo y se las arregla para evitar una excepción (extremadamente improbable, pero posible dado el tiempo específico), va a leer el archivo recién guardado, no el original.

Para entender por qué no se puede leer el archivo cuando está abierto para la escritura por otra aplicación, usted tiene que mirar en la aplicación real en .NET. (Esta es la implementación en .Net 4.5, por lo que puede ser ligeramente diferente si está viendo una versión diferente de .Net).

Esto es lo que File.ReadAllLines() se ve realmente como:

public static string[] ReadAllLines(string path) 
{ 
    if (path == null) 
    throw new ArgumentNullException("path"); 
    if (path.Length == 0) 
    throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); 
    else 
    return File.InternalReadAllLines(path, Encoding.UTF8); 
} 


private static string[] InternalReadAllLines(string path, Encoding encoding) 
{ 
    List<string> list = new List<string>(); 
    using (StreamReader streamReader = new StreamReader(path, encoding)) 
    { 
    string str; 
    while ((str = streamReader.ReadLine()) != null) 
     list.Add(str); 
    } 
    return list.ToArray(); 
} 

Y dar un vistazo a lo que StreamReader está haciendo internamente:

internal StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool checkHost) 
{ 
    if (path == null || encoding == null) 
    throw new ArgumentNullException(path == null ? "path" : "encoding"); 
    if (path.Length == 0) 
    throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); 
    if (bufferSize <= 0) 
    throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); 
    this.Init((Stream) new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost), encoding, detectEncodingFromByteOrderMarks, bufferSize, false); 
} 

Así que aquí llegamos a la razón por la excepción es un tiro, cuando suministrado con una ruta, StreamReader crea un FileStream que tiene el parámetro FileShare establecido en Read. Esto significa que no puede compartir un archivo con otra aplicación con acceso de Lectura/Escritura al archivo. Para anular este comportamiento, debe darle un Stream con una configuración diferente para FileShare, que es lo que hice en la solución que proporcioné anteriormente.

+0

Esto tiene mucho sentido y confiaré en que funciona por ahora. – user1306322

+0

@ user1306322 funcionó para mí. Me encontré con el mismo problema exacto al leer un archivo CSV que había abierto en excel y encontré tu pregunta, pero no me satisficieron las respuestas, así que así es como lo rechacé. Entonces, si tiene alguna complicación, (aparte de las que mencioné), hágamelo saber. – psubsee2003

1

probar esto.

FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, 
System.IO.FileShare.ReadWrite) 
+2

¿Cómo hago 'string [] lines = something.ReadAllLines (myPath)' con esto? – user1306322

+0

No estoy seguro de si necesito una secuencia de archivos para leer líneas de un archivo de texto. Hay alguna otra manera de hacer esto? – user1306322

1

No se puede abrir el archivo para leer solo cuando se abre con una restricción de lectura. De lo contrario, todos los métodos, incluido ReadAllLines, funcionarán sin excepciones de permisos.

Cuestiones relacionadas