Подтвердить что ты не робот

Читайте из растущего файла на С#?

В С#/.NET(в Windows) есть способ прочитать "растущий" файл, используя поток файлов? Длина файла будет очень маленькой при открытии фильтра, но файл будет записываться другим потоком. Если /, когда поток фильтрации "догоняет" к другому потоку (то есть, когда Read() возвращает 0 байт чтения), я хочу приостановить, чтобы позволить файлу немного затухать, а затем продолжить чтение.

Я действительно не хочу использовать FilesystemWatcher и продолжать создавать новые файловые потоки (как это было предложено для файлов журналов), поскольку это не файл журнала (это видео файл, закодированный "на лету" ) и производительность является проблемой.

Спасибо,
Роберт

4b9b3361

Ответ 1

Вы можете это сделать, но вам нужно внимательно следить за позициями чтения и записи файла с помощью Stream.Seek и с соответствующей синхронизацией между потоками. Как правило, для выполнения синхронизации для данных вы должны использовать EventWaitHandle или его подкласс, и вам также необходимо будет рассмотреть синхронизацию для доступа к самому объекту FileStream (возможно, через оператор lock).

Обновление: Отвечая на этот вопрос, я реализовал нечто подобное - ситуацию, когда файл загружался в фоновом режиме, а также загружался в то же время. Я использовал буферы памяти и разместил gist, у которого есть рабочий код. (Это GPL, но это может не иметь значения для вас - в любом случае вы можете использовать принципы, чтобы делать свое дело.)

Ответ 2

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

Вызов FileStream.length действительно очень медленный, у меня не было проблем с производительностью с моим решением (я читал "журнал", начиная от 10 мб до 50 иш).

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

Ответ 3

Это работало с StreamReader вокруг файла со следующими шагами:

  • В программе, которая пишет в файл, откройте его с помощью совместного доступа к чтению, например:

    var out = new StreamWriter(File.Open("logFile.txt",  FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read));
    
  • В программе, которая читает файл, откройте его совместным использованием чтения и записи, например:

    using (FileStream fileStream = File.Open("logFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using ( var file = new StreamReader(fileStream))
    
  • Перед доступом к входному потоку проверьте, достигнут ли конец, и если да, подождите некоторое время.

    while (file.EndOfStream)
    {
        Thread.Sleep(5);
    }
    

Ответ 4

Еще одна вещь, которая может быть полезна, - это класс FileStream, на котором есть свойство ReadTimeOut, которое определяется как:

Получает или задает значение в миллисекундах, которое определяет, как долго поток попытается прочитать до истечения времени. (унаследованный от потока)

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

Выполняются ли операции чтения и записи на одном объекте? Если это так, вы можете написать свои собственные абстракции над файлом, а затем написать код связи между потоками, чтобы поток, выполняющий запись и уведомляющий поток, выполняющий чтение, когда это делается, чтобы поток, выполняющий чтение, знает, когда прекратить чтение когда он достигает EOF.