2010-09-28 35 views
13

Tôi có một tệp chứa dữ liệu mà tôi muốn theo dõi các thay đổi, cũng như thêm các thay đổi của riêng tôi. Hãy suy nghĩ như "Tail -f foo.txt".đồng thời đọc-ghi một tập tin trong C#

Dựa trên this thread, có vẻ như tôi chỉ nên tạo luồng phim và chuyển nó cho cả nhà văn và người đọc. Tuy nhiên, khi người đọc đến cuối tập tin gốc, nó không nhìn thấy các bản cập nhật tôi viết.

Tôi biết nó có vẻ giống như một tình huống kỳ lạ ... nó là một thử nghiệm hơn để xem nếu nó có thể được thực hiện.

Đây là trường hợp ví dụ tôi đã cố gắng:


foo.txt:
một
b
c
d
e
f


 string test = "foo.txt"; 
     System.IO.FileStream fs = new System.IO.FileStream(test, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite); 

     var sw = new System.IO.StreamWriter(fs); 
     var sr = new System.IO.StreamReader(fs); 

     var res = sr.ReadLine(); 
     res = sr.ReadLine(); 
     sw.WriteLine("g"); 
     sw.Flush(); 
     res = sr.ReadLine(); 
     res = sr.ReadLine(); 
     sw.WriteLine("h"); 
     sw.Flush(); 
     sw.WriteLine("i"); 
     sw.Flush(); 
     sw.WriteLine("j"); 
     sw.Flush(); 
     sw.WriteLine("k"); 
     sw.Flush(); 
     res = sr.ReadLine(); 
     res = sr.ReadLine(); 
     res = sr.ReadLine(); 
     res = sr.ReadLine(); 
     res = sr.ReadLine(); 
     res = sr.ReadLine(); 

Sau khi vượt qua "f", trình đọc trả về giá trị rỗng.

+0

Một người đăng tải đã đặt thứ gì đó về việc có hai luồng tệp trỏ đến cùng một đối tượng ... đã hoạt động.Ngay cả khi người đọc đến cuối tệp, nếu người viết cập nhật, luồng người đọc nhận được cả hai kết quả. – tbischel

+0

Vâng, đó là tôi xóa bài đăng của tôi sau khi nó không hoạt động như tôi mong đợi. Tôi đã xóa nó với một lời giải thích lý do tại sao ... – MarkPflug

Trả lời

20

Ok, hai chỉnh sửa sau ...

Điều này sẽ hiệu quả. Lần đầu tiên tôi thử nó, tôi nghĩ rằng tôi đã quên đặt FileMode.Append trên oStream.

string test = "foo.txt"; 

var oStream = new FileStream(test, FileMode.Append, FileAccess.Write, FileShare.Read); 
var iStream = new FileStream(test, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 

var sw = new System.IO.StreamWriter(oStream); 
var sr = new System.IO.StreamReader(iStream); 
var res = sr.ReadLine(); 
res = sr.ReadLine(); 
sw.WriteLine("g"); 
sw.Flush(); 
res = sr.ReadLine(); 
res = sr.ReadLine(); 
sw.WriteLine("h"); sw.Flush(); 
sw.WriteLine("i"); sw.Flush(); 
sw.WriteLine("j"); sw.Flush(); 
sw.WriteLine("k"); sw.Flush(); 
res = sr.ReadLine(); 
res = sr.ReadLine(); 
res = sr.ReadLine(); 
res = sr.ReadLine(); 
res = sr.ReadLine(); 
res = sr.ReadLine(); 
+0

Tôi đã biên soạn FileShare.ReadWrite của oStream. – Mehmet

1

Nếu bạn thêm cuộc gọi vào StreamReader.DiscardBufferedData(), điều đó có thay đổi hành vi không?

+0

điều này làm cho luồng đọc đi null ngay sau khi tôi gọi nó. – tbischel

3

Tôi tin rằng mỗi khi bạn viết một ký tự, bạn sẽ tiến lên vị trí dòng, vì vậy lần đọc tiếp theo sẽ được đọc sau ký tự bạn vừa viết. Điều này xảy ra vì trình đọc luồng và trình ghi luồng của bạn đang sử dụng cùng một FileStream. Sử dụng một luồng phim khác hoặc tìm kiếm -1 ký tự trở lại trong luồng sau mỗi lần viết.

+0

cũng là cách tôi xen kẽ các bài viết và đọc là để xem nếu đây là trường hợp. Người đọc vẫn đọc chính xác theo thứ tự, nó chỉ không thấy bất kỳ dữ liệu mới được thêm vào bởi người viết. – tbischel

2

Rất khó bạn sẽ hài lòng với bất kỳ giải pháp nào cho vấn đề này liên quan đến việc sử dụng cùng một luồng để đọc và viết. Điều đó đặc biệt đúng nếu bạn đang cố đọc đuôi của tệp bằng cách sử dụng StreamReader.

Bạn muốn có hai luồng tệp khác nhau. Luồng ghi có thể là StreamWriter nếu bạn muốn. Luồng đọc phải là luồng nhị phân (tức là tạo bằng File.OpenRead hoặc FileStream.Create), đọc byte thô từ tệp và chuyển đổi thành văn bản. Câu trả lời của tôi cho this question hiển thị các khái niệm cơ bản về cách thực hiện.

9

@mikerobi là chính xác, khi bạn ghi vào luồng, con trỏ tệp được thay đổi và được chuyển đến cuối luồng. Những gì bạn không đếm là StreamReader có bộ đệm riêng của nó. Nó đọc 1024 byte từ tệp và bạn sẽ nhận được kết quả từ bộ đệm đó. Cho đến khi bộ đệm hết, nó phải đọc lại từ FileStream. Không tìm thấy gì vì con trỏ tập tin nằm ở cuối tập tin.

Bạn thực sự cần phải tách riêng FileStream, mỗi tệp có con trỏ tệp riêng của họ đều có hy vọng thực hiện công việc này.

+0

Cảm ơn Hans, tôi đã tìm cách xác nhận điều này trong việc cố gắng tự mình phát triển một giải pháp. Thật hữu ích khi thấy rằng tôi dường như đang đi đến cùng một kết luận. – jpierson

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