使用 .net 方法但不使用 powershell cmdlet 的文件
File in use with .net method but not with powershell cmdlet
要在 powershell 中打开和读取文件,我使用以下两种方法之一:
Get-Content $path
或
[System.IO.File]::OpenRead($path)
在读取另一个进程正在使用的日志文件时,Get-Content 似乎没有任何问题。然后,与 .NET 方法相比,powershell cmdlet 速度较慢并且使用更多内存。但是,当我尝试使用 .NET 方法时,出现以下错误:
"The process cannot access the file 'XYZ' because it is being used by
another process."
问题 1:为什么 .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
}
非常感谢任何帮助!
PS!我使用的是 powershell 2.0,无法终止正在使用该文件的进程。另外我没有文件的写入权限,只能读取。
PetSerAl,像往常一样,提供了一个简洁的评论,提供了一个有效的解决方案并暗示了一个解释:
要防止 "The process cannot access the file 'XYZ' because it is being used by another process."
错误,您必须使用共享模式 FileShare.ReadWrite
打开文件,以便其他想要 写入 [=39] 的进程=] 文件不会被拒绝访问。
这就是 Get-Content
(总是)在幕后所做的事情,这解释了为什么当您使用 it.
时问题不会浮出水面
相比之下,[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
是一个不错的选择。我们广泛使用它并且性能适合我们的场景。
Gets the specified number of lines from the end of a file or other item.
This parameter is introduced in Windows PowerShell 3.0.
You can use the "Tail" parameter name or its alias, "Last".
要在 powershell 中打开和读取文件,我使用以下两种方法之一:
Get-Content $path
或
[System.IO.File]::OpenRead($path)
在读取另一个进程正在使用的日志文件时,Get-Content 似乎没有任何问题。然后,与 .NET 方法相比,powershell cmdlet 速度较慢并且使用更多内存。但是,当我尝试使用 .NET 方法时,出现以下错误:
"The process cannot access the file 'XYZ' because it is being used by another process."
问题 1:为什么 .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
}
非常感谢任何帮助!
PS!我使用的是 powershell 2.0,无法终止正在使用该文件的进程。另外我没有文件的写入权限,只能读取。
PetSerAl,像往常一样,提供了一个简洁的评论,提供了一个有效的解决方案并暗示了一个解释:
要防止 "The process cannot access the file 'XYZ' because it is being used by another process."
错误,您必须使用共享模式 FileShare.ReadWrite
打开文件,以便其他想要 写入 [=39] 的进程=] 文件不会被拒绝访问。
这就是 Get-Content
(总是)在幕后所做的事情,这解释了为什么当您使用 it.
相比之下,[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
是一个不错的选择。我们广泛使用它并且性能适合我们的场景。
Gets the specified number of lines from the end of a file or other item.
This parameter is introduced in Windows PowerShell 3.0.
You can use the "Tail" parameter name or its alias, "Last".