Pregunta

Tengo algunos archivos .csv, que estoy usando como parte de un banco de pruebas. Puedo abrirlos y leerlos sin problemas a menos que ya tengo el archivo abierto en Excel, en cuyo caso me sale un IOException:

  

System.IO.IOException: El proceso no tiene acceso al archivo 'TestData.csv' porque está siendo utilizado por otro proceso

.

Este es un fragmento del banco de pruebas:

using (CsvReader csv = new CsvReader(new StreamReader(new FileStream(fullFilePath, FileMode.Open, FileAccess.Read)), false))
{
    // Process the file
}

Es esto una limitación de StreamReader? I puede abrir el archivo en otras aplicaciones (Notepad ++ por ejemplo) para que no pueda ser un O / S problema. Tal vez tengo que utilizar alguna otra clase? Si alguien sabe cómo puedo conseguir alrededor de esto (aparte de cerrar Excel!) Yo estaría muy agradecido.

¿Fue útil?

Solución

Como dice Jared, no se puede hacer esto a menos que la otra entidad que tiene el archivo abierto permite compartir lee. Excel permite compartir lecturas, incluso para los archivos que tiene abierto para escritura. Por lo tanto, debe abrir el filestream con el FileShare.ReadWrite parámetro.

El parámetro FileShare es a menudo mal entendido. Indica lo que otro abridores del archivo puede hacer. Se aplica a pasado, así como abridores de futuros. Piense en FileShare no como una prohibición retroactivo sobre abridores anteriores (por ejemplo, Excel), pero una restricción que no debe ser violado con la corriente abierta o cualquier futuro se abre.

En el caso de la actual intento de abrir un archivo, FileShare.Read dice "abrir este archivo para mí con éxito sólo si ningún abridores anteriores han abierto que solamente para leer". Si especifica FileShare.Read en un archivo que está abierto para escribir por Excel, su abierta fallará, ya que violaría la restricción, porque Excel tiene abierto para escribir .

Debido a que Excel tiene el archivo abierto para escritura, debe abrir el archivo con FileShare.ReadWrite si quieres su abierta para tener éxito. Otra forma de pensar del parámetro FileShare: especifica "acceso a los archivos del otro tipo".

Ahora supongamos que un escenario diferente, en el que va a abrir un archivo que no está abierto actualmente por cualquier otra aplicación. FileShare.Read dice "futuros abridores pueden abrir el archivo sólo con acceso de lectura".

Como es lógico, esta semántica tienen sentido - FileShare.Read significa, que no desea leer el archivo si el otro tipo ya se está escribiendo, y que no quieren que el otro tipo para escribir el archivo si ya está leerlo. FileShare.ReadWrite significa, que están dispuestos a leer el archivo incluso si el otro chico que está escribiendo, y no tiene problema en dejar que otro abridor de escribir el archivo mientras lo está leyendo.

En ningún caso este permiso múltiples escritores. FileShare es similar a una base de datos de IsolationLevel. Su configuración deseada aquí depende de la "consistencia" garantiza que requiera.

Ejemplo:

using (Stream s = new FileStream(fullFilePath, 
                                 FileMode.Open,
                                 FileAccess.Read,
                                 FileShare.ReadWrite))
{
  ...
}

o

using (Stream s = System.IO.File.Open(fullFilePath, 
                                      FileMode.Open, 
                                      FileAccess.Read, 
                                      FileShare.ReadWrite))
{
}

Adición:

El href="http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx" documentación rel="noreferrer"> es un poco más delgada. Si desea obtener los hechos rectos, vaya a la documentación la función CreateFile Win32 , lo que explica el concepto FileShare mejor.

Otros consejos

Editar

Aún no estoy 100% seguro de por qué esto es la respuesta, pero se puede solucionar este problema mediante el paso FileShare.ReadWrite al constructor FileStream.

using (CsvReader csv = new CsvReader(new StreamReader(new FileStream(fullFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)), false)
{
  ...
}

Mi curiosidad tiene una bodega de mí en este momento y estoy tratando de entender por qué esto es la respuesta en particular. Si lo averigüe más tarde voy a actualizar esto con la información.

La mejor documentación en realidad parece estar en la href="http://msdn.microsoft.com/en-us/library/aa363858.aspx" rel="noreferrer"> CreateFile función . Esta es la función .Net llamará bajo el capó con el fin de abrir un archivo (crear el archivo es un nombre poco apropiado). Tiene una mejor documentación de cómo funciona el aspecto intercambio de abrir un archivo. Otra opción es simplemente leer la respuesta de Cheeso

Si otro proceso tiene un archivo abierto a menudo se puede utilizar File.Copy y abra la copia. No es una solución elegante, sino un pragmático.

Otro problema es que si se abre un FileStream con FileShare.ReadWrite, se abre posterior de ese archivo debe especificar, además, FileShare.ReadWrite, o se obtendrá el error 'Otro proceso está utilizando este archivo'.

Uso de los System.Diagnostics;

Usted puede simplemente llamar Process.Start ( “nombre de archivo y ruta”)

No está seguro de si eso ayuda, pero eso es lo que he usado para implementar un botón de vista previa PDF en nuestra intranet.

scroll top