[英]Powershell - performance issues using out-file in a foreach loop
以下脚本将 XML 转换为特定的 CSV 格式以提供特定的源系统。 它工作正常,但性能非常慢。 我相信问题是因为 Out-File 正在打开 - 关闭每一行的文件。 有一个更好的方法吗?
$url = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml'
$result = Invoke-RestMethod -Uri $url
$elements = $result.Envelope.Cube
foreach($element in $elements)
{
foreach($x in $element.Cube)
{
foreach($y in $x.Cube)
{
$time = $x.time.ToString() -replace "-"
$output = $time + "`t" + $y.currency.ToString() + "`t" + $y.rate.ToString()
$output | Out-File -Append ".\rates.csv"
}
}
}
我相信问题是因为 Out-File 正在打开 - 关闭每一行的文件
这确实是原因,因此加快命令速度的关键是将 pipe 的所有数据调用到Out-File
的单个调用中,您可以通过将foreach
循环包装在您的脚本块( {... }
)中来实现使用&
调用, 调用运算符:
& {
foreach ($element in $elements) {
foreach ($x in $element.Cube) {
foreach ($y in $x.Cube) {
$time = $x.time.ToString() -replace "-"
# Synthesize and output the line to save.
$time + "`t" + $y.currency.ToString() + "`t" + $y.rate.ToString()
}
}
}
} | Out-File .\rates.csv
以上保留了 PowerShell 的典型流式管道行为,将 output 行一一发送到Out-File
。
鉴于您的数据已经在 memory 中,您可以通过在foreach
循环周围使用$(...)
而不是& {... }
来加快操作速度,即使用$()
, 子表达式 operator 。
也就是说,内存数据允许更快的处理:
通过绕过管道,而是将所有 output 行作为参数传递。
此外,假设您正在将文本保存到文件中,通过使用Set-Content
来加快速度。
Set-Content
的默认编码不同于Out-File
的:活动 ANSI 代码页的编码与 UTF-16LE(“Unicode”); 在PowerShell [Core] 7+中,所有 cmdlet 始终默认为无 BOM 的 UTF-8; 根据需要使用-Encoding
参数。 最后,您可以利用 PowerShell 的成员枚举从foreach
循环中消除一层嵌套。
# Adjust -Encoding as needed.
Set-Content -Encoding utf8 .\rates.csv -Value $(
foreach ($x in $elements.Cube) {
foreach ($y in $x.Cube) {
$time = $x.time.ToString() -replace "-"
# Synthesize and output the output line.
$time + "`t" + $y.currency.ToString() + "`t" + $y.rate.ToString()
}
}
)
尝试这个:
$url = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml'
$result = Invoke-RestMethod -Uri $url
$elements = $result.Envelope.Cube
$outputAll = New-Object -TypeName "System.Collections.ArrayList"
foreach($element in $elements)
{
foreach($x in $element.Cube)
{
foreach($y in $x.Cube)
{
$time = $x.time.ToString() -replace "-"
$output = $time + "`t" + $y.currency.ToString() + "`t" + $y.rate.ToString()
$null = $outputAll.add($output)
}
}
}
$outputAll | Out-File -Append ".\rates.csv"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.