在 Windows 上编辑 1GB 以上文本文件的第一行/最后一行,而无需将整个文件加载到内存中

在 Windows 上编辑 1GB 以上文本文件的第一行/最后一行,而无需将整个文件加载到内存中

我有一些纯文本数据文件(“CSV”),大小高达 3GB,只需删除前 3 行文本,并在末尾添加一个空行。由于我有很多这样的文件,所以我想找到一种快速的方法来做到这一点。

这些第一行的问题在于它们不是 CSV 数据,而是不符合列格式的随机文本。因此,SQL Server 的 Bulk Insert 语句无法处理这些文件。

一种选择是使用 PowerShell 脚本,但使用 Get-content 或流总是需要读取整个文件并再次完全输出。有没有办法直接修改磁盘上的文件,而无需将其完全加载到内存中并重新创建文件?

最好,我正在寻找一种 PowerShell 方法来执行此操作。尽管第三方工具可能也很有趣...

答案1

从文件开头删除内容需要重写该文件。

您可以使用tail -n +4 input.csv > output.csv删除前三行(在我的低端服务器上,15 GB 的 Wikipedia 转储需要 105 秒,即每秒约 150 MB)。在 Windows 上,tail可以使用 Cygwin 例如

答案2

我猜没有办法不读取内存中的整个文件,至少我不知道。

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

这将是一个需要将整个文件加载到内存中的 PowerShell 解决方案。

  • 使用 搜索某个位置的每个 csv gci
  • foreach循环遍历找到的带有别名的csv 文件%
  • 获取其全部内容(可能需要一些时间)get-content
  • 选择所有内容但跳过前三行select -skip
  • 并使用 将该内容设置为文件set-content
  • 最后一行将向文件添加一个新行add-content

编辑:-ReadCount您可以尝试通过在调用中添加参数来加快整个过程get-content

-读取计数 (int)

指定一次通过管道发送多少行内容。默认值为 1。值为 0(零)表示一次发送所有内容。

此参数不会改变显示的内容,但会影响显示内容所需的时间。随着 ReadCount 值的增加,返回第一行所需的时间会增加,但操作的总时间会减少。这在非常大的项目上会产生明显的差异。

编辑2:get-content用它测试过readcount。遗憾的是我找不到大于 89mb 的文本文件。但差异已经很明显了:

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要走的路

答案3

经过深入挖掘,我认为这一问题可以归结为以下几点:

有没有办法直接就地编辑使用 NTFS 格式化的 HDD 上的文件?

我的答案是,可以使用十六进制编辑器在硬盘级别直接进行更改,进行较小的更改,但进行诸如删除整个文件部分之类的巨大更改可能会破坏文件系统。因此,问题又归结为:

NTFS 是否支持编辑分配给文件的数据块而不重写整个文件?

我的猜测是……不会。但我有兴趣了解更多有关此问题的细节……

相关内容