2010-08-24 7 views
34

Necesito leer un archivo de Windows que puede estar bloqueado, pero no quiero crear ningún tipo de bloqueo que impida que otros procesos escriban en el archivo.¿Cuál es la forma menos invasiva de leer un archivo bloqueado en C# (quizás en modo inseguro)?

Además, incluso si el archivo está bloqueado para uso exclusivo, me gustaría ver qué hay dentro.

Aunque este no es mi caso de uso exacto, considere cómo leer un archivo de base de datos SQL/Exchange mientras está en uso y montado. No quiero causar corrupción, pero aún quiero ver el interior del archivo y leerlo.

Respuesta

11

La respuesta no es aceptada correcto. Si el archivo está realmente bloqueado, no puede simplemente cambiar el recurso compartido de archivos. Esto funcionaría si el bloqueo se ha configurado con esta opción de compartir archivos también, pero eso no significa que sea el caso. De hecho, puede probar la solución @CaffGeek con bastante facilidad abriendo el archivo sin FileShare.ReadWrite y luego tratando de abrirlo con este indicador para ReadWrite. Obtendrá que el archivo está siendo utilizado por otro proceso.

Código: contenido de cadena; var filePath = "e: \ test.txt";

 //Lock Exclusively the file 
     var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write); 

     //CaffGeek solution 
     using (FileStream fileStream = new FileStream(
     filePath, 
     FileMode.Open, 
     FileAccess.Read, 
     FileShare.ReadWrite)) 
     { 
      using (StreamReader streamReader = new StreamReader(fileStream)) 
      { 
       content = streamReader.ReadToEnd(); 
      } 
     } 

Como puedes ver, se bloquea. Este resultado es el mismo con cualquier método FileStream como File.Open. Se bloqueará lo que sea que pongas para FileShare durante la etapa abierta.

 //OPEN FOR WRITE with exclusive 
     var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write); 


     //OPEN FOR READ with file share that allow read and write 
     var x = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); //Crash 

Copiar el archivo tampoco es una opción. Usted puede intentar usted mismo abriendo el archivo de forma exclusiva y tratar de copiar el archivo en el Explorador de Windows o mediante código:

 var filePath = "e:\\test.txt"; 
     var filePathCopy = "e:\\test.txt.bck"; 

     //Lock the file 
     var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write); 

     File.Copy(filePath, filePathCopy); 
     var x = File.Open(filePathCopy, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
     using (var reader = new StreamReader(x)) 
     { 
      content = reader.ReadToEnd(); 
     } 

     r.Close(); 
     File.Delete(filePathCopy); 

Este accidente código cuando se golpea la línea File.Copy. La excepción es la misma que antes: el archivo está siendo utilizado por otro proceso.

Tiene que matar el proceso que tiene el bloqueo del archivo si quiere leerlo O si tiene el código fuente del archivo que está bloqueando el archivo para cambiar este para usar FileShare.ReadWrite en lugar de solo FileShare.Write.

+1

Eso o quizás puedo usar la copia de seguridad, las API de VSS de alguna manera – LamonteCristo

+0

De hecho, he tenido éxito al copiar el archivo, pero me he encontrado con problemas de bloqueo en la copia (¿algún estado se ha copiado junto?) – user3734274

1

Probablemente pueda crear una copia y leerla, incluso si el archivo está bloqueado.

O tal vez un StreamReader en un FileStream dependiendo de cómo SQL abrió el archivo?

new FileStream("c:\myfile.ext", FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
+0

Eso podría funcionar ... pero una base de datos es grande. Tal vez necesito saber cómo funciona Copy, ya que quiero ese tipo de acceso. – LamonteCristo

44

Puede hacerlo sin copiar el archivo, consulte el artículo this:

El truco es usar FileShare.ReadWrite (del artículo):

private void LoadFile() 
{ 
    try 
    { 
     using(FileStream fileStream = new FileStream(
      "logs/myapp.log", 
      FileMode.Open, 
      FileAccess.Read, 
      FileShare.ReadWrite)) 
     { 
      using(StreamReader streamReader = new StreamReader(fileStream)) 
      { 
       this.textBoxLogs.Text = streamReader.ReadToEnd(); 
      } 
     } 
    } 
    catch(Exception ex) 
    { 
     MessageBox.Show("Error loading log file: " + ex.Message); 
    } 
} 
+0

Acabo de publicar una nueva pregunta en respuesta a esto: http://stackoverflow.com/questions/3560921/is-it-better-to-use-the-using-directive-in-c-or-the-dispose -method-does-th – LamonteCristo

+1

Esto funciona perfectamente para leer el archivo de log4net. –

Cuestiones relacionadas