使用.net方法而不是PowerShell cmdlet的文件

问题描述 投票:2回答:2

要在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并且无法终止正在使用该文件的进程。此外,我没有对该文件的写访问权限,只是阅读。

.net powershell powershell-v2.0
2个回答
3
投票

像往常一样,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中始终是可选的。


1
投票

如果你可以转移到更高版本的PowerShell(至少v3.0),那么Get-Content -Tail是一个不错的选择。我们广泛使用它,性能对我们的场景有益。

Official docs

从文件或其他项的末尾获取指定的行数。 此参数是在Windows PowerShell 3.0中引入的。 您可以使用“Tail”参数名称或其别名“Last”。

© www.soinside.com 2019 - 2024. All rights reserved.