2012-04-27 2 views
6

Мне нужно разобрать большой файл CSV в режиме реального времени, в то время как он изменен (добавлен) другим процессом. По большому счету я имею в виду ~ 20 ГБ на данный момент и медленно растет. Приложение должно обнаруживать и сообщать о некоторых аномалиях в потоке данных, для чего ему нужно хранить только небольшую информацию о состоянии (O(1)).Разбор больших текстовых файлов, измененных на лету

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

Если я не ошибаюсь, это не должно быть такой проблемой для реализации, но я хотел знать, есть ли общий способ/библиотека, которая решает некоторые из этих проблем уже?

Примечание: Мне не нужен парсер CSV. Мне нужна информация о библиотеке, которая упрощает чтение строк из файла, который изменяется на лету.

+0

Можно ли остановить обработку csv? Если да, я предлагаю вам передать его в СУБД. – Oybek

+0

@ Ойбек: можете ли вы это немного уточнить? Процесс, который добавляется к файлу, постоянно работает, и мне нужно постоянно анализировать данные по строкам (с задержкой в ​​несколько секунд). – Groo

+0

Предполагаю, что вы не контролируете процесс, испускающий файл? –

ответ

1

Существует небольшая проблема:

  • Чтение и разбор CSV требует TextReader
  • позиционирования не работает (а) с TextReaders.

Первая мысль: Держите ее открытой. Если и производитель, и анализатор работает в неисключительной режиме Должна быть обеспечена возможность не Readline-до-нуль, пауза, ReadLine-до-нуль и т.д.


он должен быть 7-битный ASCII , только некоторые наборы и цифры

Это позволяет отслеживать файл Position (pos + = line.Length + 2). Убедитесь, что вы открыли его с помощью . Затем вы можете повторно открыть его как простой двоичный поток, искать последнюю позицию и только затем присоединить StreamReader к этому потоку.

+0

Вы правы, это, вероятно, намного лучше, чем поиск. – Groo

+0

Crap, я даже не рассматривал многобайтовые символы, пока вы не упоминали об этом. Еще один отличный совет, спасибо! – Groo

0

Почему бы вам просто не разделить отдельный процесс/нить при каждом разборе - таким образом, вы перемещаете параллельную (на лету) часть вдали от источника данных и к вашему потоку данных - так Теперь вы просто должны понять, как собрать результаты из всех нитей ...

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

Вы можете запустить программу diff в двух версиях и выбрать оттуда, в зависимости от того, насколько хорошо сформирован источник данных csv: изменяет ли записи уже записанные записи? Или он просто добавляет новые записи?Если да, то вы можете просто отделились новый материал (последняя позиция на ток-EOF) в новый файл, и обработать те, на досуге в фоновом потоке:

  • нити опроса запоминает размер последнего файла
  • когда файл становится больше: искать с последней позиции до конца, сохранить временный файл
  • фонового поток обрабатывает все временные файлы все еще остались, в порядке создания/модификации
+1

Ну, размер данных, добавляемых каждую секунду, относительно невелик по сравнению со всем размером файла, и именно поэтому я бы хотел не читать его каждый раз (это может быть легко 50 ГБ после недели измерений). И поскольку данные только добавляются, а файлы очень большие, diff не является практичным. Я также не понимаю, что касается потоковой обработки: поскольку это операция с диском, чтение не принесет пользы из нескольких потоков, оно может работать только медленнее IMO и шаг, на котором я пишу частичный файл на диск, а затем снова открывать его кажется излишним (если я его копирую, я также могу разобрать его). – Groo

2

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