要在powershell中打开和读取文件,我使用以下两种方法之一:
Get-Content $path
要么
[System.IO.File]::OpenRead($path)
在读取另一个进程Get-Content正在使用的日志文件时,它似乎没有任何问题。然后,与.NET方法相比,powershell cmdlet很慢并且使用更多内存。当我尝试使用.NET方法时,我收到以下错误:
“该进程无法访问文件'XYZ',因为它正由另一个进程使用。”
Q1:为什么.net方法不能访问文件而powershell cmdlet可以?
Q2:我怎么能用.net方法读取文件?由于Get-Content对于大约80 MB的日志文件来说太慢了。我通常只阅读最后一行:
$line = ""
$lineBreak = Get-Date -UFormat "%d.%m.%Y "
$bufferSize = 30
$buffer = New-Object Byte[] $bufferSize
$fs = [System.IO.File]::OpenRead($logCopy)
while (([regex]::Matches($line, $lineBreak)).Count -lt $n) {
$fs.Seek(-($line.Length + $bufferSize), [System.IO.SeekOrigin]::End) | Out-Null
$fs.Read($buffer, 0, $bufferSize) | Out-Null
$line = [System.Text.Encoding]::UTF8.GetString($buffer) + $line
}
$fs.Close()
($line -split $lineBreak) | Select -Last $n
}
Author to original code on StackOverflow
任何帮助非常感谢!
PS!我正在使用powershell 2.0并且无法终止正在使用该文件的进程。此外,我没有对该文件的写访问权限,只是阅读。
像往常一样,PetSerAl提供了一个简短的评论,提供了一个有效的解决方案并暗示了一个解释:
要防止"The process cannot access the file 'XYZ' because it is being used by another process."
错误,必须使用共享模式FileShare.ReadWrite
打开该文件,以便不会拒绝其他想要写入该文件的进程访问。
这就是Get-Content
(总是)在幕后做的事情,这解释了为什么当你使用它时问题不会出现。
相比之下,[System.IO.File]::OpenRead()
默认为共享模式FileShare.Read
,这意味着其他进程可以读取,但不能写入同一文件。
因此,请改用[System.IO.File]::Open()
,它允许您明确指定共享模式:
$fs = [IO.File]::Open($path,
[IO.FileMode]::Open,
[IO.FileAccess]::Read,
[IO.FileShare]::ReadWrite)
# ...
$fs.Close()
请注意,我从上面的类型名称中省略了System.
组件;此组件在PowerShell中始终是可选的。
如果你可以转移到更高版本的PowerShell(至少v3.0),那么Get-Content -Tail
是一个不错的选择。我们广泛使用它,性能对我们的场景有益。
从文件或其他项的末尾获取指定的行数。 此参数是在Windows PowerShell 3.0中引入的。 您可以使用“Tail”参数名称或其别名“Last”。