Эффективный анализ большого текстового файла в C #

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

A7PS A8PN A6PP23 ...

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

Я думаю, я мог бы просто открыть StreamReader и пролистайте строку за строкой, разделив пробел на символ. Посмотрим, встречался ли код, и добавил 1 к счетчику этого кода. Тем не менее, это, вероятно, довольно наивно, учитывая размер данных.

Кто-нибудь знает эффективный алгоритм для обработки такого рода обработки?

ОБНОВЛЕНИЕ:

Хорошо, так что консенсус, похоже, мой подход вдоль правильных линий

Мне было бы интересно услышать такие вещи, как - что более эффективно - StreamReader. TextReader, BinaryReader

Какова лучшая структура для хранения моего словаря результатов? HashTable, SortedList, HybridDictionary

Если нет разрыва строки в файле (мне еще не дали пример), будет просто неэффективно разбивать все это на пространство?

По существу, Я пытаюсь сделать его как можно более быстрым

, еще раз спасибо

6
задан ChrisCa 27 August 2010 в 13:12
поделиться

3 ответа

Ваш подход выглядит нормально.

  1. Читать построчно
  2. Разделять каждую строку пробелом
  3. Добавить запись в словарь если его еще нет и если он существует, сделайте значение ++
5
ответ дан 8 December 2019 в 20:11
поделиться

Я бы сказал, что в целом ваш подход правильный, но есть место для параллелизма. Я бы посоветовал вам запустить несколько потоков или задач (в .NET 4) для каждой части/фрагмента синтаксического анализа файла. Кроме того, вместо того, чтобы читать построчно, читайте по частям байтов - это повысит производительность с точки зрения дискового ввода-вывода.

Редактировать: Вот план решения.

  1. Допустим, мы будем обрабатывать M чанков N символов одновременно (потому что мы хотим ограничить объем памяти необходимое и количество используемых потоков).
  2. Выделить N*M буфер символов. Мы будем использовать этот буфер циклически.
  3. Будет использоваться модель производитель-потребитель. Производитель заполнит буфер. Это попытается найти границу слова рядом граница фрагмента (т. е. около каждого N-го персонаж). Таким образом, у нас будет M кусков приблизительно N символов с началом и конец индекса в буфере
  4. Теперь запустите M рабочих потоков для обработки каждого фрагмента. Каждый рабочий процесс будет использовать свой собственный словарь для подсчета слов, что избавит от необходимости синхронизации потоков.
  5. В конце итерации результаты будут агрегированы. Процесс необходимо повторять до тех пор, пока не будет прочитан весь файл.

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

4
ответ дан 8 December 2019 в 20:11
поделиться

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

Чтобы сохранить коды и количество, вы должны использовать структуру данных, которая позволяет выполнять поиск и вставку за время O(log n). SortedDictionary сделает это на C#.

РЕДАКТИРОВАТЬ:

Какая структура лучше всего подходит для хранения моего словаря результатов? HashTable, SortedList, HybridDictionary

Поскольку порядок сортировки кажется не обязательным, HybridDictionary или Dictionary в большинстве случаев будут работать лучше. SortedList, вероятно, будет самым медленным решением, потому что вставки занимают O (n). Вы должны провести несколько тестов с различными реализациями, если производительность так важна.

0
ответ дан 8 December 2019 в 20:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: