одновременное чтение и запись файла в C # - PullRequest
14 голосов
/ 29 сентября 2010

У меня есть файл, содержащий данные, которые я хотел бы отслеживать изменения, а также добавлять свои собственные изменения.Думайте как "Tail -f foo.txt".

Исходя из этой цепочки , похоже, что я должен просто создать поток файлов и передать его как автору, так и читателю.Однако, когда читатель достигает конца исходного файла, он не видит обновления, которые я пишу сам.

Я знаю, что это кажется странной ситуацией ... это скорее эксперимент, чтобы увидеть, можно ли это сделать.

Вот пример, который я пробовал:


foo.txt:
a
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();

После прохождения "f"читатель возвращает ноль.

Ответы [ 5 ]

22 голосов
/ 29 сентября 2010

Хорошо, два редактирования позже ...

Это должно работать. В первый раз, когда я попробовал это, я думаю, что забыл установить FileMode.Append для 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();
9 голосов
/ 29 сентября 2010

@ mikerobi правильно, когда вы записываете в поток, указатель файла изменяется и перемещается в конец потока. На что вы не рассчитываете, так это на то, что StreamReader имеет свой собственный буфер. Он читает 1024 байта из файла, и вы получите результаты из этого буфера. Пока буфер не исчерпан, он должен снова прочитать из FileStream. Ничего не найдено, потому что указатель файла находится в конце файла.

Вам действительно нужно разделить FileStreams, каждый из которых имеет собственный указатель файла, чтобы иметь какую-либо надежду на выполнение этой работы.

3 голосов
/ 29 сентября 2010

Я считаю, что каждый раз, когда вы пишете символ, вы продвигаете позицию потока, поэтому следующее чтение пытается прочитать после символа, который вы только что написали. Это происходит потому, что ваш потоковый читатель и потоковый писатель используют один и тот же FileStream. Используйте другой файловый поток или ищите -1 символ обратно в потоке после каждой записи.

2 голосов
/ 29 сентября 2010

Маловероятно, что вы будете довольны каким-либо решением этой проблемы, которое предполагает использование одного и того же потока для чтения и записи. Это особенно верно, если вы пытаетесь прочитать хвост файла, используя StreamReader.

Вы хотите иметь два разных файловых потока. Поток записи может быть StreamWriter, если хотите. Поток чтения должен быть двоичным потоком (то есть создавать с File.OpenRead или FileStream.Create), читать необработанные байты из файла и преобразовывать в текст. Мой ответ на на этот вопрос показывает основы того, как это делается.

1 голос
/ 29 сентября 2010

Если вы добавите вызов к StreamReader.DiscardBufferedData(), это изменит поведение?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...