我看到一些我似乎无法解释的奇怪行为。
流式传输文本文件的代码工作正常。
$journalPath = "$(Split-Path $($script:myInvocation.myCommand.path) -parent)\Journals"
$journals = Get-ChildItem $journalPath -filter "journal.*.txt"
Write-Host "Streaming"
foreach ($journal in $journals) {
$reader = [System.IO.File]::OpenText("$journalPath\$journal")
do {
$line = ($reader.ReadLine()).Trim()
if (-not ($line.StartsWith("'"))) {
Write-Host $line
}
} until ($line -eq $null)
$reader.Close()
}
但是,如果我退出Write-Host行,我会得到
You cannot call a method on a null-valued expression.
第9行,$reader.ReadLine()
行。为什么简单的Write-Line会产生这种影响呢?
答案 0 :(得分:0)
与(所谓的 pretest )While () {…}
循环不同,所有(所谓的 posttest )Do {…} While ()
以及Do {…} Until ()
}循环将始终执行其代码块至少一次,因为条件发生在循环结束。
下一个示例显示逐行循环文件内容的基本方案,包括 inept ,显示读取行是否可以在当前迭代/重复中计算为空值表达式。请注意,您无需拨打.NET File Class [System.IO.File]
。
$journalPath = "$(Split-Path $($script:myInvocation.myCommand.Path) -parent)\Journals"
$journals = Get-ChildItem $journalPath -filter "journal*.txt"
foreach ($journal in $journals) {
Write-Host "`r`n" (" " * 10) "testing " $journal.Name
'DO {} WHILE ( $line -ne $null )'
$reader = [System.IO.File]::OpenText("$journalPath\$journal")
Do {
$line = $reader.ReadLine()
Write-Host (" " * 14) ($line -eq $null) $reader.EndOfStream
} While ( $line -ne $null )
$reader.Close()
'DO {} UNTIL ( $line -eq $null )'
$reader = [System.IO.File]::OpenText("$journalPath\$journal")
Do {
$line = $reader.ReadLine()
Write-Host (" " * 14) ($line -eq $null) $reader.EndOfStream
} Until ( $line -eq $Null )
$reader.Close()
'DO {} WHILE ( -not $reader.EndOfStream )'
$reader = [System.IO.File]::OpenText("$journalPath\$journal")
Do {
$line = $reader.ReadLine()
Write-Host (" " * 14) ($line -eq $null) $reader.EndOfStream
} While ( -not $reader.EndOfStream )
$reader.Close()
'DO {} UNTIL ( $reader.EndOfStream )'
$reader = [System.IO.File]::OpenText("$journalPath\$journal")
Do {
$line = $reader.ReadLine()
Write-Host (" " * 14) ($line -eq $null) $reader.EndOfStream
} Until ( $reader.EndOfStream )
$reader.Close()
'WHILE ( -not $reader.EndOfStream ) {}'
$reader = [System.IO.File]::OpenText("$journalPath\$journal")
While ( -not $reader.EndOfStream) {
$line = $reader.ReadLine()
Write-Host (" " * 14) ($line -eq $null) $reader.EndOfStream
}
$reader.Close()
'FOREACH-OBJECT {}'
$journal | Get-Content -Encoding UTF8 | ForEach-Object {
Write-Host (" " * 14) ($_ -eq $null)
}
}
任何人都可以看到唯一可接受的方案是那些包含'FOREACH-OBJECT {}'
和'WHILE ( -not $reader.EndOfStream ) {}'
子标题的方案:
PS D:\PShell> D:\PShell\SO\37898929.ps1
testing journal37898929-none_lines.txt
DO {} WHILE ( $line -ne $null )
True True
DO {} UNTIL ( $line -eq $null )
True True
DO {} WHILE ( -not $reader.EndOfStream )
True True
DO {} UNTIL ( $reader.EndOfStream )
True True
WHILE ( -not $reader.EndOfStream ) {}
FOREACH-OBJECT {}
testing journal37898929-some_lines.txt
DO {} WHILE ( $line -ne $null )
False False
False False
False True
True True
DO {} UNTIL ( $line -eq $null )
False False
False False
False True
True True
DO {} WHILE ( -not $reader.EndOfStream )
False False
False False
False True
DO {} UNTIL ( $reader.EndOfStream )
False False
False False
False True
WHILE ( -not $reader.EndOfStream ) {}
False False
False False
False True
FOREACH-OBJECT {}
False
False
False
PS D:\PShell>
进一步阅读:PowerShell loops: For, Foreach, While, Do-Until, Continue, Break