powershell - 如何在 PowerShell 中将文件作为流逐行处理

标签 powershell stream

我正在处理一些数 GB 的文本文件,并希望使用 PowerShell 对它们进行一些流处理。这很简单,只需解析每一行并提取一些数据,然后将其存储在数据库中。

不幸的是,get-content | %{whatever($_)} 似乎将管道此阶段的整组行保留在内存中。它的速度也出奇的慢,需要很长时间才能真正读完。

所以我的问题分为两部分:

  1. 如何让它逐行处理流而不将整个内容缓冲在内存中?我希望避免为此使用几GB RAM。
  2. 如何让它运行得更快? PowerShell 迭代 get-content 似乎比 C# 脚本慢 100 倍。

我希望我在这里做了一些愚蠢的事情,比如缺少 -LineBufferSize 参数或其他东西......

最佳答案

如果您确实要处理数千兆字节的文本文件,请不要使用 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' } }

更新:如果您仍然不害怕,那么尝试使用 .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()
}

更新2

有关于可能更好/更短的代码的评论。 for 的原始代码没有任何问题,也不是伪代码。但阅读循环的较短(最短?)变体是

$reader = [System.IO.File]::OpenText("my.log")
while($null -ne ($line = $reader.ReadLine())) {
    $line
}

关于powershell - 如何在 PowerShell 中将文件作为流逐行处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4192072/

相关文章:

powershell - Cmdlet 实例持续多长时间?

windows - 将文件添加到文件夹时运行 .bat 文件的 Powershell 脚本

c# - AcroPDFLib 从 Windows 窗体 C# .NET 中的流打开 PDF 文件

c# - 异步 Twitter 搜索

stream - 检测 TCP 流中的某个字符串(命令)

powershell - Powershell和Plink-如何捕获消息 “Access Denied”

regex - 在Powershell中获取2个字符之间的所有文本

powershell - 将 Remove-Item 输出到日志文件

java - 如何增加Android音频流的数量?

java - 数据输入流困惑