在 PowerShell 中,将标准输入重定向到文件的常规方法是通过管道传输文件的内容:
Get-Content input-file.txt | Write-Host
但是,如果文件非常大,PowerShell 就会开始消耗大量内存。使用 small-ReadCount
似乎可以加快Get-Content
将行输入命令的速度,但内存消耗仍然很大。
为什么内存使用率这么高?PowerShell是否将文件的内容保留在内存中,即使它不需要?有什么办法可以缓解吗?
在 PowerShell 中,将标准输入重定向到文件的常规方法是通过管道传输文件的内容:
Get-Content input-file.txt | Write-Host
但是,如果文件非常大,PowerShell 就会开始消耗大量内存。使用 small-ReadCount
似乎可以加快Get-Content
将行输入命令的速度,但内存消耗仍然很大。
为什么内存使用率这么高?PowerShell是否将文件的内容保留在内存中,即使它不需要?有什么办法可以缓解吗?
以下函数将使用 .NET StreamReader类逐行读取文件,并将每一行发送到管道中。在近 2,000,000 行日志文件 (~186 MB) 上执行时,将其发送到Out-Null
我的内存使用量仅增加了 10 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
本文提出了一种可能的解决方案。使用旧的命令行:
cmd.exe /C "ECHO < input-file.txt"
旧式输入重定向不会以相同的方式消耗内存。
然而,这非常难看,并且会让你做一些奇怪的事情来构建更复杂的命令。我更喜欢纯 PowerShell 解决方案。