sco*_*obi 87 powershell stream
我正在使用一些多GB的文本文件,并希望使用PowerShell对它们进行一些流处理.这很简单,只需解析每一行并提取一些数据,然后将其存储在数据库中.
不幸的是,get-content | %{ whatever($_) }
似乎在管道的这个阶段保持整个行集在内存中.它的速度也非常慢,需要花费很长时间才能完全阅读.
所以我的问题是两部分:
get-content
进行迭代的PowerShell 似乎比C#脚本慢100倍.我希望我在这里做一些愚蠢的事情,比如错过一个-LineBufferSize
参数或什么......
Rom*_*min 90
如果您真的要处理多GB文本文件,请不要使用PowerShell.即使你找到一种方法来阅读它,在PowerShell中处理大量行的速度也会很慢,你无法避免这种情况.即使是简单的循环也很昂贵,比如1000万次迭代(在你的情况下非常真实)我们有:
# "empty" loop: takes 10 seconds
measure-command { for($i=0; $i -lt 10000000; ++$i) {} }
# "simple" job, just output: takes 20 seconds
measure-command { for($i=0; $i -lt 10000000; ++$i) { $i } }
# "more real job": 107 seconds
measure-command { for($i=0; $i -lt 10000000; ++$i) { $i.ToString() -match '1' } }
Run Code Online (Sandbox Code Playgroud)
更新:如果你仍然不害怕,那么尝试使用.NET阅读器:
$reader = [System.IO.File]::OpenText("my.log")
try {
for() {
$line = $reader.ReadLine()
if ($line -eq $null) { break }
# process the line
$line
}
}
finally {
$reader.Close()
}
Run Code Online (Sandbox Code Playgroud)
更新2
有关于可能更好/更短的代码的评论.原始代码没有任何问题,for
它不是伪代码.但是阅读循环的较短(最短?)变体是
$reader = [System.IO.File]::OpenText("my.log")
while($null -ne ($line = $reader.ReadLine())) {
$line
}
Run Code Online (Sandbox Code Playgroud)
Des*_*tar 49
System.IO.File.ReadLines()
非常适合这种情况.它返回文件的所有行,但允许您立即开始迭代行,这意味着它不必将整个内容存储在内存中.
需要.NET 4.0或更高版本.
foreach ($line in [System.IO.File]::ReadLines($filename)) {
# do something with $line
}
Run Code Online (Sandbox Code Playgroud)
http://msdn.microsoft.com/en-us/library/dd383503.aspx
小智 6
如果您想直接使用PowerShell,请查看以下代码.
$content = Get-Content C:\Users\You\Documents\test.txt
foreach ($line in $content)
{
Write-Host $line
}
Run Code Online (Sandbox Code Playgroud)