CSV произвольный доступ; C # - PullRequest
6 голосов
/ 28 января 2011

У меня есть CSV-файл 10 ГБ, который представляет собой огромную квадратную матрицу. Я пытаюсь написать функцию, которая может максимально эффективно обращаться к одной ячейке матрицы, то есть к матрице [12345,20000].

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

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

Я рассмотрел сканирование файла и создание таблицы поиска для индекса первого байта каждой строки. Таким образом, если я захочу получить доступ к матрице [12345,20000], я буду стремиться к началу строки 12345, а затем сканировать строку, считая запятые, пока не достигну правильной ячейки.

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

Приветствия

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

Ответы [ 6 ]

3 голосов
/ 28 января 2011

Прежде всего, как бы вы хотели сослаться на конкретную строку? Это индекс строки, так что у вас есть другая таблица или что-то, что поможет вам узнать, какая строка вам интересна? или это по id или что-то?

Эти идеи приходят в голову

  • Ваш подход
  • Бинарный поиск. Предполагая, что у вас есть средняя длина (размер / строки), вы можете использовать бинарный поиск, чтобы найти строку, предполагая, что в строке есть идентификатор, который упорядочен и может сказать вам, если вы попали или не попали.
  • Загрузка в базу данных! Кстати, что мешает тебе это сделать? Вы даже можете использовать SQL Express - free - и чтобы обойти ограничение размера, вы можете shard свои данные для нескольких баз данных.
3 голосов
/ 28 января 2011

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

Lumenworks CSV

1 голос
/ 28 января 2011

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

Единственный вопрос - насколько велик ваш индекс. Если он слишком большой, вы можете уменьшить его, индексируя только каждую 5-ю (например) строку и сканируя в диапазоне 5 строк.

0 голосов
/ 28 января 2011

Что делать, если вы создали 12345 отдельный файл, который читается с отложенной реализацией. Каждый файл будет прочитан только в случае необходимости данных. Если данные полностью разрежены, вы можете создать структуру данных со свойством IsEmpty bool.

Вам нужно снова и снова обращаться к одному и тому же элементу или вам нужно просто прочитать каждый элемент по одному разу?

0 голосов
/ 28 января 2011

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

В прошлом вы могли писать простой код, который считывает файл переменной ширины 10 ГБ с локального диска и записывает файл фиксированной ширины 10 ГБ на локальный диск за несколько (~ 20) минут. , Если эти первоначальные инвестиции окупятся, зависит от того, сколько случайных операций чтения вам нужно сделать и как часто меняется файл, который нужно прочитать.

0 голосов
/ 28 января 2011

Я не согласен с тем, что вам не следует загружать файл в ОЗУ, особенно если вы используете 64-битную ОС.

Не должно быть проблем с выделением матрицы размером 12345x20000: это всего около 1,9 ГБ.в двойной точности.И на самом деле, даже если бы размер был больше, я все равно рекомендовал бы этот подход для 64-битной платформы (см. «Виртуальная память»).

Во-вторых, вы заявили, что ваша матрица была разреженной, следовательно, вы можете загрузить в ОЗУ, ноиспользуйте разреженное представление, чтобы сэкономить память.

В заключение, если вашему приложению требуется много доступа к вашей матрице, а производительность очень важна, размещение ее в ОЗУ определенно будет моим любимым подходом.

...