2010-08-24 8 views
34

Potrzebuję odczytać plik Windows, który może być zablokowany, ale nie chcę tworzyć blokady, która uniemożliwi zapisanie innych procesów do pliku.Jaki jest najmniej inwazyjny sposób odczytu zablokowanego pliku w języku C# (być może w trybie niebezpiecznym)?

Ponadto, nawet jeśli plik jest zablokowany do wyłącznego użytku, chciałbym zobaczyć, co jest w środku.

Chociaż nie jest to mój dokładny przypadek użycia, należy rozważyć, jak odczytać dziennik SQL/Exchange lub plik bazy danych, gdy jest on używany i podłączony. Nie chcę powodować korupcji, ale nadal chcę zobaczyć wnętrze pliku i go przeczytać.

Odpowiedz

11

Przyjęty odpowiedź nie jest poprawny. Jeśli plik jest naprawdę zablokowany, nie można po prostu zmienić udziału pliku. To działałoby, gdyby blokada została ustawiona również z tą opcją tworzenia plików, ale nie oznacza to, że tak jest. W rzeczywistości możesz przetestować rozwiązanie @CaffGeek dość łatwo, otwierając plik bez FileShare.ReadWrite i próbując otworzyć go z tą flagą do ReadWrite. Otrzymasz, że plik jest używany przez inny proces.

Kod: treść ciągów; 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(); 
      } 
     } 

Jak widać, ulega awarii. Ten wynik jest taki sam dla każdej metody FileStream, takiej jak File.Open. Spowoduje to awarię tego, co kiedykolwiek dodałeś do FileShare na otwartym etapie.

 //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 

Kopiowanie pliku nie jest również opcją. możesz spróbować siebie otwierając wyłącznie plik i spróbuj skopiować plik w Eksploratorze Windows lub za pomocą kodu:

 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); 

Ten krach kod po trafieniu linię File.Copy. Wyjątek jest taki sam jak wcześniej: plik jest używany przez inny proces.

Musisz zabić proces, który ma blokadę pliku, jeśli chcesz go odczytać LUB jeśli masz kod źródłowy pliku, który blokuje plik, aby go zmienić, aby używał FileShare.ReadWrite zamiast tylko FileShare.Write.

+1

To lub może mogę użyć kopii zapasowej, VSS API w jakiś sposób – LamonteCristo

+0

rzeczywiście mam powodzenie, kopiowanie pliku, ale uruchomić w kwestii blokady na kopii (jakiś stan jest kopiowany wzdłuż?) – user3734274

1

Prawdopodobnie możesz utworzyć kopię i ją przeczytać, nawet jeśli plik jest zablokowany.

A może StreamReader na FileStream w zależności od tego, jak SQL otworzył plik?

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

To może zadziałać ... ale baza danych jest duża. Może potrzebuję wiedzieć, jak działa Copy, skoro chcę tego typu dostępu. – LamonteCristo

44

Można to zrobić bez kopiowania pliku, zobacz this artykuł:

Sztuką jest, aby używać FileShare.ReadWrite (z artykułu):

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

Właśnie napisałem nowe pytanie w odpowiedzi na to: http://stackoverflow.com/questions/3560921/is-it-better-to-use-the-using-directive-in-c-or-the-dispose -method-does-th – LamonteCristo

+1

Działa to doskonale do odczytu pliku dziennika log4net. –

Powiązane problemy