我有一些纯文本数据文件(“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 是否支持编辑分配给文件的数据块而不重写整个文件?
我的猜测是……不会。但我有兴趣了解更多有关此问题的细节……