3

У меня есть несколько файлов с текстовыми данными ("CSV") размером до 3 ГБ, и мне просто нужно удалить первые 3 строки текста и добавить пустую строку в конце. Поскольку у меня много этих файлов, я хотел бы найти быстрый способ сделать это.

Проблема с этими первыми строками заключается в том, что это не данные CSV, а случайный текст, который не соответствует формату столбца. Из-за этого оператор SQL Server Bulk Insert не может обрабатывать эти файлы.

Одним из вариантов может быть использование скрипта PowerShell, но использование Get-content или потоков всегда будет включать чтение всего файла и его полную выдачу снова. Есть ли способ напрямую изменить файл на диске, не загружая его полностью в память и не воссоздавая файл?

Предпочтительно, я ищу способ PowerShell сделать это. Хотя сторонние инструменты тоже могут быть интересными ...

3 ответа3

3

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

$csv = gci "C:\location" -filter *.csv | % { 
    (Get-Content $_.FullName | select -skip 3) | Set-Content $_.FullName 
    Add-Content -path $_.FullName -value ""
}

Это будет решение PowerShell, которое требует загрузки всего файла в память.

  • искать каждый CSV из местоположения с помощью gci ,
  • перебрать найденные CSV-файлы с псевдонимом foreach % ,
  • получить весь их контент (может занять некоторое время) с помощью get-content ,
  • выбрать все, но пропустить первые 3 строки select -skip
  • и установите этот контент в файл с set-content .
  • последняя строка добавит новую строку в файл add-content

Изменить: Вы можете попытаться сделать все это быстрее, добавив параметр -ReadCount к вашему вызову get-content .

-ReadCount (int)

Определяет, сколько строк контента отправляется через конвейер одновременно. Значением по умолчанию является 1. Значение 0 (ноль) отправляет весь контент за один раз.

Этот параметр не изменяет отображаемое содержимое, но влияет на время, необходимое для отображения содержимого. По мере увеличения значения ReadCount время, необходимое для возврата первой строки, увеличивается, но общее время операции уменьшается. Это может существенно повлиять на очень большие предметы.

Edit2: я тестировал get-content с помощью readcount . к сожалению, я не смог найти текстовый файл размером более 89 МБ. но разница уже значительна

PS C:\Windows\System32> Measure-Command { gc "C:\Pub.log" -readcount 0 }


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 22
Ticks             : 10224578
TotalDays         : 1.18340023148148E-05
TotalHours        : 0.000284016055555556
TotalMinutes      : 0.0170409633333333
TotalSeconds      : 1.0224578
TotalMilliseconds : 1022.4578




PS C:\Windows\System32> Measure-Command { gc "C:\Pub.log" -readcount 1 }


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 10
Milliseconds      : 594
Ticks             : 105949457
TotalDays         : 0.000122626686342593
TotalHours        : 0.00294304047222222
TotalMinutes      : 0.176582428333333
TotalSeconds      : 10.5949457
TotalMilliseconds : 10594.9457

так что get-content $_.FullName -readcount 0 - путь

2

Удаление содержимого из начала файла требует переписать файл.

Вы можете использовать tail -n +4 input.csv > output.csv чтобы удалить первые три строки (требуется 105 секунд для дампа Википедии на 15 ГБ на моем сервере нижнего уровня, то есть около 150 МБ в секунду). На Windows tail доступен с Cygwin, например

0

Пройдя немного глубже, я думаю, что этот вопрос сводится к следующему:

Есть ли способ отредактировать файл на жестком диске, отформатированном с использованием NTFS, непосредственно на месте?

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

Поддерживает ли NTFS редактирование блоков данных, назначенных файлу, без перезаписи всего файла?

Мое предположение будет ... нет. Но мне было бы интересно узнать немного больше о деталях этого ...

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .