尝试实现一个自定义的类似尾巴的功能,在检查了几个示例之后,我来到了下面的代码,它工作得很好(不加载整个文件来读取 X 结束行,适用于网络路径......)
我遇到的问题是我不如何将流指针移动到其当前位置之前的 10 行?
作为一种解决方法,我将指针移动到当前位置之前 1024 个字节,但我不知道这真正涉及到多少行。
$sr=New-Object System.IO.StreamReader($fs)
$lastPosition=$sr.BaseStream.Length # final position of the file
$currentPosition=$lastPosition - 1024
谁能指出我正确的方向吗?
这是完整的代码:
function tail{
[cmdletBinding()]
Param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$filename, # path
[int]$n=10, # number of lines to output
[switch]$continous, # continue to monitor for changes ?
[switch]$hilight # hilight lines containing keywords ?
)
# Initialising stuff
$hilightError=@("erreur","error","fatal","critic")
$hilightWarning=@("attention","warning","notice")
$errorColor="red"
$warningColor="darkyellow"
if ( (test-Path $filename) -eq $false){
write-Error "Cant read this file !"
exit
}
function tailFile($ptr){
# return each line from the pointer position to the end of file
$sr.BaseStream.Seek($ptr,"Begin")
$line = $sr.ReadLine()
while ( $line -ne $null){
$e=$w=$false
if( $hilight){
$hilightError | %{ $e = $e -or ($line -match $_) } # find error keywords ?
if( $e) {wh $line -ForegroundColor $errorColor }
else{
$hilightWarning | %{ $w = $w -or ($line -match $_ ) } # find warning keywords ?
if($w){ wh $line -ForegroundColor $warningColor }
else{ wh $line}
}
}
else{ #no hilight
wh $line
}
$line = $sr.ReadLine()
}
}
# Main
$fs=New-Object System.IO.FileStream ($filename,"OpenOrCreate", "Read", "ReadWrite",8,"None") # use ReadWrite sharing permission to not lock the file
$sr=New-Object System.IO.StreamReader($fs)
$lastPosition=$sr.BaseStream.Length # final position of the file
$currentPosition=$lastPosition - 1024 # take some more bytes (to get the last lines)
tailfile $currentPosition
if($continous){
while(1){
start-Sleep -s 1
# have the file changed ?
if ($sr.BaseStream.Length -eq $lastPosition){
write-verbose "no change..."
continue
}
else {
tailfile $lastPosition
$lastPosition = $sr.BaseStream.Position
write-Verbose "new position $lastPosition"
}
}
}
$sr.close()
}