Одновременное чтение и запись файла в C#
У меня есть файл, содержащий данные, к которым я хотел бы отслеживать изменения, а также добавлять свои собственные изменения. Думайте как "Tail -f foo.txt".
Исходя из этого потока, похоже, что я должен просто создать файловый поток и передать его как автору, так и читателю. Однако, когда читатель достигает конца исходного файла, он не видит обновления, которые я пишу сам.
Я знаю, это кажется странной ситуацией... это скорее эксперимент, чтобы увидеть, можно ли это сделать.
Вот пример, который я пробовал:
foo.txt:
б
с
d
е
е
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 ответов
Хорошо, два изменения позже...
Это должно работать. В первый раз, когда я попробовал это, я думаю, что забыл установить 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();
@mikerobi правильно, когда вы пишете в поток, указатель файла изменяется и перемещается в конец потока. На что вы не рассчитываете, так это на то, что StreamReader имеет свой собственный буфер. Он читает 1024 байта из файла, и вы получите результаты из этого буфера. Пока буфер не исчерпан, он должен снова читать из FileStream. Ничего не найдено, потому что указатель файла находится в конце файла.
Вам действительно нужно разделить FileStreams, каждый со своим указателем файла, чтобы иметь хоть какую-то надежду на выполнение этой работы.
Я считаю, что каждый раз, когда вы пишете символ, вы продвигаете позицию потока, поэтому следующее чтение пытается прочитать после символа, который вы только что написали. Это происходит потому, что ваш потоковый читатель и потоковый писатель используют один и тот же FileStream. Используйте другой файловый поток или ищите -1 символ обратно в потоке после каждой записи.
Маловероятно, что вы будете довольны любым решением этой проблемы, которое предполагает использование одного и того же потока для чтения и записи. Это особенно верно, если вы пытаетесь прочитать хвост файла, используя StreamReader
,
Вы хотите иметь два разных файловых потока. Поток записи может быть StreamWriter
если хочешь. Поток чтения должен быть двоичным потоком (т.е. создавать с File.OpenRead
или же FileStream.Create
), читать необработанные байты из файла и преобразовывать в текст. Мой ответ на этот вопрос показывает основы того, как это делается.
Если вы добавите звонок в StreamReader.DiscardBufferedData()
, это меняет поведение?