2012-12-06 5 views
12

У меня есть много больших файлов csv (по 1-10 gb каждый), которые я импортирую в базы данных. Для каждого файла мне нужно заменить 1-ю строку, чтобы я мог форматировать заголовки для имен столбцов. Мое текущее решение:Быстро заменить первую строку большого файла

using (var reader = new StreamReader(file)) 
{ 
    using (var writer = new StreamWriter(fixed)) 
    { 
     var line = reader.ReadLine(); 
     var fixedLine = parseHeaders(line); 
     writer.WriteLine(fixedLine); 

     while ((line = reader.ReadLine()) != null) 
      writer.WriteLine(line); 
    } 
} 

Что такое быстрый способ заменить только линию 1 без перебора любой другой линии этих огромных файлов?

+0

Я бы просто сделал это из командной строки. 'copy headerfile + csvfile newfile' Вы можете создать пакетный файл со всеми файлами, которые необходимо изменить. (О, за исключением того, что, похоже, вы не знаете, какие заголовки будут заблаговременно. Если нет, это не поможет.) –

+0

Если инструмент, который вы используете, принимает вход через 'stdin': вместо файла , вы можете создать поток, состоящий из заголовков и тела, и подать их в свой инструмент импорта, когда вам это нужно. например 'cat headerfile bigfile | import_tool' –

+0

Это очень чувствительно к длинам fixedLine и первой строки. Может ли fixedLine быть больше? Может ли строка2 перейти к концу файла? –

ответ

7

Если вы можете гарантировать, что fixedLine такой же длины (или меньше), как line, вы можете обновить файлы на месте вместо их копирования.

Если нет, возможно, вы можете получить небольшое улучшение производительности путем доступа к .BaseStream вашего StreamReader и StreamWriter и делать большие блочные копии (с использованием, например, буфер в 32К байт), чтобы сделать копирование, которое будет по крайней мере устранить время, проведенное с проверкой каждого персонажа, чтобы увидеть, является ли это символом конца строки, как это происходит сейчас с reader.ReadLine().

+0

Если бы это было меньше, что бы вы сделали с «свободным» пространством? Поместите его в пространство? – Jodrell

+0

Возможно, но это будет зависеть от формата. В CSV-файле я мог бы процитировать элементы заголовка и добавлять пробелы после запятых. – prprcupofcoffee

+1

+1. @Jodrell, да, пробелы в большинстве случаев игнорируются для CSV - поэтому использование их для заполнения будет ОК (я попытался предложить его в моем идентичном ответе :)).Пробелы также безопасны для большинства кодировок - поэтому они могут быть записаны непосредственно в поток в виде байтов, если это необходимо. –

6

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

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

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

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

Смежные вопросы