在Powershell中将标准输入重定向到大文件 - 内存消耗

3
在PowerShell中,将标准输入重定向到文件的常规方法是将文件内容传送到管道:
Get-Content input-file.txt | Write-Host

然而,如果文件非常大,PowerShell会开始消耗大量的内存。使用较小的-ReadCount似乎可以加快Get-Content开始将行提供给命令的速度,但内存消耗仍然很大。

为什么内存使用率这么高?是因为PowerShell保留了文件内容在内存中,即使它不需要吗?有没有一些方法来减轻这种情况?

2个回答

4
以下函数将使用.NET StreamReader类逐行读取文件,并将每行发送到管道中。将其发送到Out-Null后,内存使用量仅在执行近200万行日志文件(~186 MB)时增加了几十KB:
function Get-ContentByLine {
  param (
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)][PsObject]$InputObject
  )

  begin {
    $line = $null
    $fs = [System.IO.File]::OpenRead($InputObject)
    $reader = New-Object System.IO.StreamReader($fs)
  }

  process {
    $line = $reader.ReadLine()
    while ($line -ne $null) {
        $line
        $line = $reader.ReadLine()
    }
  }

  end {
    $reader.Dispose();
    $fs.Dispose();
  }
}

你可以这样调用它:
PS C:\> Get-ContentByLine "C:\really.big.log" | Out-Null

1
有趣。当然使用.NET是有道理的,但我以前从未见过begin/process/end。一些细节供像我这样不熟悉的人参考。如果PowerShell已经内置了这样的功能,那将非常好。 - jpmc26

0

这篇文章提出了一个可能的解决方案。使用旧的命令行:

cmd.exe /C "ECHO < input-file.txt"

旧式的输入重定向不会以同样的方式消耗内存。

然而,这非常丑陋,并且需要您执行一些奇怪的操作来构建更复杂的命令。我更喜欢一个纯PowerShell解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接