2009-09-11 2 views
16

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

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

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

+0

Я обновил свой ответ. –

ответ

6

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

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

+0

Я рассмотрю это ... для пинков, может быть проще просто записать результат кодирования в память (т. Е. Использовать двойной буфер), а затем отправить его в сетевой и кеш-файл одновременно? –

4

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

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

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

+1

Вопрос о специальных скидках с использованием наблюдателя из-за проблем с производительностью. –

+0

Да, я заметил. добавлено еще к моему ответу относительно предварительной работы. – EKS

+0

Вам не обязательно вызывать FileStream.Length в читателе, если все, что вы делаете, читаете, насколько можете, а затем ожидаете большего количества данных. Какую задержку вы наблюдаете за запуском наблюдателя? Это зависит от нагрузки на машину? –

2

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

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

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

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

+0

Как мог этот ответ получить +3, если установка ReadTimeOut на FileStream вызывает исключение? : S –

4

Это работало с StreamReader вокруг файла, выполнив следующие действия:

  1. В программе, которая записывает в файл, откройте его с помощью совместного чтения, как это:

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

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

    while (file.EndOfStream) 
    { 
        Thread.Sleep(5); 
    } 
    
Смежные вопросы