2010-08-10 16 views
70

Ho un servizio Windows scrive il suo registro in un file di testo in un formato semplice.Come posso leggere un file di testo senza bloccarlo?

Ora, ho intenzione di creare una piccola applicazione per leggere il registro del servizio e mostra sia il registro esistente che quello aggiunto come visualizzazione live.

Il problema è che il servizio blocca il file di testo per l'aggiunta delle nuove righe e allo stesso tempo l'applicazione di visualizzazione blocca il file per la lettura.

il codice di servizio:

void WriteInLog(string logFilePath, data) 
{ 
    File.AppendAllText(logFilePath, 
         string.Format("{0} : {1}\r\n", DateTime.Now, data)); 
} 

Il Codice spettatore:

int index = 0; 
private void Form1_Load(object sender, EventArgs e) 
     { 
      try 
      { 
       using (StreamReader sr = new StreamReader(logFilePath)) 
       { 
        while (sr.Peek() >= 0) // reading the old data 
        { 
         AddLineToGrid(sr.ReadLine()); 
         index++; 
        } 
        sr.Close(); 
       } 

       timer1.Start(); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     } 


private void timer1_Tick(object sender, EventArgs e) 
     { 
      using (StreamReader sr = new StreamReader(logFilePath)) 
      { 
       // skipping the old data, it has read in the Form1_Load event handler 
       for (int i = 0; i < index ; i++) 
        sr.ReadLine(); 

       while (sr.Peek() >= 0) // reading the live data if exists 
       { 
        string str = sr.ReadLine(); 
        if (str != null) 
        { 
         AddLineToGrid(str); 
         index++; 
        } 
       } 
       sr.Close(); 
      } 
     } 

C'è qualche problema nel mio codice in lettura e scrittura modo?

Come risolvere il problema?

+0

Possibile duplicato di [È possibile impedire a StreamReader di bloccare un file di testo mentre è in uso?] (Https://stackoverflow.com/questions/1606349/can-i-prevent-a-streamreader-from-locking -a-text-file-while-it-is-in-use) –

risposta

94

È necessario assicurarsi che sia il servizio che il lettore aprano il file di registro non esclusivamente. Prova questo:

Per l'utilizzo del servizio di un'istanza FileStream creato come segue:

var outStream = new FileStream(logfileName, FileMode.Open, 
           FileAccess.Write, FileShare.ReadWrite); 

Per il lettore utilizzano lo stesso, ma modificare l'accesso del file:

var inStream = new FileStream(logfileName, FileMode.Open, 
           FileAccess.Read, FileShare.ReadWrite); 

Buona fortuna!

+0

C'è anche la versione ReadLines() su http://stackoverflow.com/questions/5338450/file-readlines-without-locking-it – Colin

+0

Perfect - Avevo pensato che File.Open() con FileAccess.Read fosse sufficiente, ma non è. Questo è, però. :) – neminem

2

Hai provato a copiare il file, quindi a leggerlo?

Basta aggiornare la copia ogni volta che vengono apportate modifiche di grandi dimensioni.

+1

Ho provato questo e non è la soluzione migliore. La copia del file richiede troppo tempo, perché un file da 4 MB richiede 20 secondi. – Seichi

6

Il problema è quando si sta scrivendo sul registro che si sta bloccando il file esclusivamente in modo che StreamReader non sia autorizzato ad aprirlo del tutto.

È necessario provare ad aprire il file in modalità a sola lettura.

using (FileStream fs = new FileStream("myLogFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
{ 
    using (StreamReader sr = new StreamReader(fs)) 
    { 
     while (!fs.EndOfStream) 
     { 
      string line = fs.ReadLine(); 
      // Your code here 
     } 
    } 
} 
+0

Come ora so, 'File.ReadAllText()' fallisce con la modalità di sola lettura. –

+0

@modosansreves yeah Ho rimosso quella parte della risposta poiché [docs] (http://msdn.microsoft.com/en-us/library/ms143368 (v = vs.100) .aspx) indica che genererà un 'UnauthorizedAccessException' se il file è di sola lettura - deve averlo perso al momento della risposta! – James

26

Impostazione esplicita della modalità di condivisione durante la lettura del file di testo.

+2

non è necessario chiudere esplicitamente lo stream, poiché StreamReader.Dispose lo chiude automaticamente. – nothrow

+2

Credo che la condivisione file dovrebbe essere impostata su ENTRAMBI i flussi di lettura e scrittura e non solo la lettura. –

10
new StreamReader(File.Open(logFilePath, 
          FileMode.Open, 
          FileAccess.Read, 
          FileShare.ReadWrite)) 

-> questo non blocca il file.

+0

Sembra funzionare durante la lettura dei dati. Quando si scrive l'errore del file bloccato si presenta. – webzy

5

Mi ricordo di aver fatto la stessa cosa un paio di anni fa. Dopo alcune query google ho trovato questo:

FileStream fs = new FileStream(@”c:\test.txt”, 
            FileMode.Open, 
            FileAccess.Read,   
            FileShare.ReadWrite); 

cioè utilizzare l'attributo FileShare.ReadWrite su FileStream().

(trovato su Balaji Ramesh's blog)

0

Questo metodo vi aiuterà a più veloce leggere un file di testo e senza bloccarlo.

private string ReadFileAndFetchStringInSingleLine(string file) 
    { 
     StringBuilder sb; 
     try 
     { 
      sb = new StringBuilder(); 
      using (FileStream fs = File.Open(file, FileMode.Open)) 
      { 
       using (BufferedStream bs = new BufferedStream(fs)) 
       { 
        using (StreamReader sr = new StreamReader(bs)) 
        { 
         string str; 
         while ((str = sr.ReadLine()) != null) 
         { 
          sb.Append(str); 
         } 
        } 
       } 
      } 
      return sb.ToString(); 
     } 
     catch (Exception ex) 
     { 
      return ""; 
     } 
    } 

Spero che questo metodo ti possa aiutare.

Problemi correlati