2010-08-10 22 views
70

Tôi có dịch vụ cửa sổ ghi nhật ký của nó trong một tệp văn bản ở định dạng đơn giản.Làm cách nào để đọc một tệp văn bản mà không khóa nó?

Bây giờ, tôi sẽ tạo một ứng dụng nhỏ để đọc nhật ký của dịch vụ và hiển thị cả nhật ký hiện có và nhật ký được thêm làm chế độ xem trực tiếp.

Sự cố là dịch vụ khóa tệp văn bản để thêm dòng mới và đồng thời ứng dụng trình xem khóa tệp để đọc.

Bộ luật Dịch vụ:

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

Người xem Code:

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ó bất kỳ vấn đề trong mã của tôi trong việc đọc và viết cách?

Cách giải quyết sự cố?

+0

Bản sao có thể có của [Tôi có thể ngăn StreamReader khóa tệp văn bản trong khi đang sử dụng không?] (Https://stackoverflow.com/questions/1606349/can-i-prevent-a-streamreader-from-locking -a-text-file-while-it-is-in-use) –

Trả lời

94

Bạn cần đảm bảo rằng cả dịch vụ và người đọc đều mở tệp nhật ký không độc quyền. Hãy thử điều này:

Đối với việc sử dụng dịch vụ một trường hợp FileStream tạo như sau:

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

Đối với người đọc sử dụng tương tự nhưng thay đổi quyền truy cập tập tin:

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

Chúc may mắn!

+0

Cũng có phiên bản ReadLines() tại http://stackoverflow.com/questions/5338450/file-readlines-without-locking-it – Colin

+0

Hoàn hảo - Tôi đã nghĩ rằng File.Open() với FileAccess.Read là đủ, nhưng nó không phải là. Đây là, mặc dù. :) – neminem

2

Bạn đã thử sao chép tệp rồi đọc tệp chưa?

Chỉ cần cập nhật bản sao bất cứ khi nào có thay đổi lớn.

+1

Tôi đã thử điều này và nó không phải là giải pháp tốt nhất. Việc sao chép tệp mất quá nhiều thời gian, đối với tệp 4mb mất khoảng 20 giây. – Seichi

6

Vấn đề là khi bạn đang ghi vào nhật ký, bạn chỉ khóa tệp xuống để StreamReader của bạn hoàn toàn không được phép mở tệp đó.

Bạn cần thử mở tệp ở chế độ chỉ đọc.

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

Bây giờ tôi biết, 'File.ReadAllText()' không thành công với chế độ chỉ đọc. –

+0

@modosansreves vâng tôi đã xóa phần câu trả lời đó là [tài liệu] (http://msdn.microsoft.com/en-us/library/ms143368 (v = vs.100) .aspx) tuyên bố rằng nó sẽ ném một 'UnauthorizedAccessException' nếu tệp chỉ đọc - phải bỏ lỡ điều đó tại thời điểm trả lời! – James

26

Rõ ràng thiết lập chế độ chia sẻ trong khi đọc tệp văn bản.

using (FileStream fs = new FileStream(logFilePath, 
             FileMode.Open, 
             FileAccess.Read,  
             FileShare.ReadWrite)) 
{ 
    using (StreamReader sr = new StreamReader(fs)) 
    { 
     while (sr.Peek() >= 0) // reading the old data 
     { 
      AddLineToGrid(sr.ReadLine()); 
      index++; 
     } 
    } 
} 
+2

không nhất thiết phải đóng luồng một cách rõ ràng, vì StreamReader.Dispose tự động đóng nó. – nothrow

+2

Tôi tin rằng chia sẻ tệp nên được đặt trên cả hai dòng đọc và ghi và không chỉ đọc. –

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

-> điều này không khóa tệp.

+0

Dường như làm việc khi đọc dữ liệu. Khi viết các tập tin bị khóa lỗi đi lên. – webzy

5

Tôi nhớ đã làm điều tương tự vài năm trước. Sau một số truy vấn google tôi đã tìm thấy điều này:

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

tức là sử dụng thuộc tính FileShare.ReadWrite trên FileStream().

(tìm thấy trên Balaji Ramesh's blog)

0

Phương pháp này sẽ giúp bạn nhanh nhất đọc một tập tin văn bản và không có khóa nó.

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 ""; 
     } 
    } 

Hy vọng phương pháp này sẽ giúp bạn.

Các vấn đề liên quan