Windows 7では、巨大なファイルの最後のn行(1〜4 Gb)を取得する必要があります。企業の制限により、組み込みではないコマンドは実行できません。問題は、見つけたすべてのソリューションがファイル全体を読み取るように見えるため、非常に遅いことです。
これを迅速に達成できますか?
ノート:
ここでの解決策 Windows PowershellのUnix tail同等のコマンド は機能しませんでした。 -wait
を使用しても高速にはなりません。 -tail
がありません(それが高速に動作するかどうかわかりません)。
PS:head
とtail
には関連する質問がかなりありますが、速度の問題に焦点を合わせていません。したがって、役に立つ回答または受け入れられている回答は、ここでは役に立ちません。例えば。、
txtファイルの最後の10行を表示するCMD.EXEバッチスクリプト
単一のWindowsコマンドを使用してファイルからN行を抽出
https://superuser.com/questions/859870/windows-equivalent-of-the-head-c-command
これはどうですか(デモ用に最後の8バイトを読み取ります):
$fpath = "C:\10GBfile.dat"
$fs = [IO.File]::OpenRead($fpath)
$fs.Seek(-8, 'End') | Out-Null
for ($i = 0; $i -lt 8; $i++)
{
$fs.ReadByte()
}
[〜#〜] update [〜#〜]。バイトを文字列として解釈するには(ただし、正しいエンコーディングを選択してください-ここではUTF8が使用されます):
$N = 8
$fpath = "C:\10GBfile.dat"
$fs = [IO.File]::OpenRead($fpath)
$fs.Seek(-$N, [System.IO.SeekOrigin]::End) | Out-Null
$buffer = new-object Byte[] $N
$fs.Read($buffer, 0, $N) | Out-Null
$fs.Close()
[System.Text.Encoding]::UTF8.GetString($buffer)
更新2。最後のM行を読み込むには、結果にM改行文字シーケンスよりも多くなるまで、部分ごとにファイルを読み込みます。
$M = 3
$fpath = "C:\10GBfile.dat"
$result = ""
$seq = "`r`n"
$buffer_size = 10
$buffer = new-object Byte[] $buffer_size
$fs = [IO.File]::OpenRead($fpath)
while (([regex]::Matches($result, $seq)).Count -lt $M)
{
$fs.Seek(-($result.Length + $buffer_size), [System.IO.SeekOrigin]::End) | Out-Null
$fs.Read($buffer, 0, $buffer_size) | Out-Null
$result = [System.Text.Encoding]::UTF8.GetString($buffer) + $result
}
$fs.Close()
($result -split $seq) | Select -Last $M
より大きな$buffer_size
-理想的には、これはディスク操作を少なくするために予想される平均行長に等しい。また、$ seqにも注意してください-これは\r\n
あるいは単に \n
。これは、エラー処理や最適化を行わない非常に汚いコードです。
PowerShell 3以降を使用している場合は、-Tail
のGet-Content
パラメーターを使用して、最後のn
行を取得できます。
Get-content -tail 5 PATH_TO_FILE;
ローカルSSDの34MBテキストファイルでは、get-content |select -last 5
の8.5秒に対して1ミリ秒で返されました
Aziz Kabyshevによる素晴らしい答え で、速度の問題を解決し、いくつかのグーグルで、私はこのスクリプトを使用することになりました
$fpath = $Args[1]
$fs = [IO.File]::OpenRead($fpath)
$fs.Seek(-$Args[0], 'End') | Out-Null
$mystr = ''
for ($i = 0; $i -lt $Args[0]; $i++)
{
$mystr = ($mystr) + ([char[]]($fs.ReadByte()))
}
$fs.Close()
Write-Host $mystr
これを含むバッチファイルから呼び出す
@PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '.\myscript.ps1' %1 %2"
(おかげで バッチファイルからPowerShellスクリプトを実行する方法 )。
これは答えではなく、sancho.sの答えに対する返信としての大きなコメントです。
バッチファイルから小さなPowerShellスクリプトを使用する場合は、以下の方法を使用することをお勧めします。これはより簡単で、すべてのコードを同じバッチファイルに保持することができます。
@PowerShell ^
$fpath = %2; ^
$fs = [IO.File]::OpenRead($fpath); ^
$fs.Seek(-%1, 'End') ^| Out-Null; ^
$mystr = ''; ^
for ($i = 0; $i -lt %1; $i++) ^
{ ^
$mystr = ($mystr) + ([char[]]($fs.ReadByte())); ^
} ^
Write-Host $mystr
%End PowerShell%