问题:我需要搜索另一个进程当前正在使用的大型日志文件。我无法停止此其他过程,也无法锁定.log文件。我需要快速搜索此文件,而无法将其全部读取到内存中。我知道StreamReader()是最快的,但是我想不出如何避免它试图抓住文件上的锁。
$p = "Seachterm:Search"
$files = "\\remoteserver\c\temp\tryingtofigurethisout.log"
$SearchResult= Get-Content -Path $files | Where-Object { $_ -eq $p }
以下内容不起作用,因为我无法锁定文件。
$reader = New-Object System.IO.StreamReader($files)
$lines = @()
if ($reader -ne $null) {
while (!$reader.EndOfStream) {
$line = $reader.ReadLine()
if ($line.Contains($p)) {
$lines += $line
}
}
}
$lines | Select-Object -Last 1
这需要太长时间:
get-content $files -ReadCount 500 |
foreach { $_ -match $p }
如果能快速有效地(在内存方面)搜索大型日志文件,我将不胜感激。
答案 0 :(得分:0)
也许这对您有用。它会尝试尽可能快地读取文件的各行,但与您的第二种方法有所不同(与[System.IO.File]::ReadAllLines()
所执行的操作大致相同)。
要收集行,我使用List对象,该对象的执行速度比使用+=
附加到数组的速度快
$p = "Seachterm:Search"
$path = "\\remoteserver\c$\temp\tryingtofigurethisout.log"
if (!(Test-Path -Path $path -PathType Leaf)) {
Write-Warning "File '$path' does not exist"
}
else {
try {
$fileStream = [System.IO.FileStream]::new($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
$streamReader = [System.IO.StreamReader]::new($fileStream)
# or use this syntax:
# $fileMode = [System.IO.FileMode]::Open
# $fileAccess = [System.IO.FileAccess]::Read
# $fileShare = [System.IO.FileShare]::ReadWrite
# $fileStream = New-Object -TypeName System.IO.FileStream $path, $fileMode, $fileAccess, $fileShare
# $streamReader = New-Object -TypeName System.IO.StreamReader -ArgumentList $fileStream
# use a List object of type String or an ArrayList to collect the strings quickly
$lines = New-Object System.Collections.Generic.List[string]
# read the lines as fast as you can and add them to the list
while (!$streamReader.EndOfStream) {
$lines.Add($streamReader.ReadLine())
}
# close and dispose the obects used
$streamReader.Close()
$fileStream.Dispose()
# do the 'Contains($p)' after reading the file to not slow that part down
$lines.ToArray() | Where-Object { $_.Contains($p) } | Select-Object -Last 1
}
catch [System.IO.IOException] {}
}
基本上,它执行您的第二个代码所执行的操作,但是区别在于仅使用StreamReader
时,文件会以[System.IO.FileShare]::Read
打开,而此代码会使用[System.IO.FileShare]::ReadWrite
打开文件
请注意,使用此方法可能会引发异常,因为另一个应用程序对该文件具有写权限,因此try{...} catch{...}
希望有帮助