获取Windows中一个巨大文件的最后n行或字节(如Unix的尾部).避免耗时的选择

san*_*ica 19 windows powershell batch-file tail

我需要在Windows 7中检索最后n行巨大文件(1-4 Gb).由于公司限制,我无法运行任何非内置命令.问题是我找到的所有解决方案似乎都读取整个文件,所以它们非常慢.

这可以快速完成吗?

笔记:

  1. 我设法快速获得前n行.
  2. 如果我得到最后n个字节就可以了.(我使用这个/sf/answers/1325563991/作为前n个字节).

这里的解决方案Windows Powershell中的Unix tail等效命令不起作用.使用-wait不会让它变快.我没有-tail(我不知道它是否会起作用).

PS:有相当的几个相关问题headtail,但不能集中在速度的问题.因此,有用或可接受的答案在这里可能没用.例如,

Windows相当于'tail'命令

CMD.EXE批处理脚本,用于显示txt文件中的最后10行

使用单个Windows命令从文件中提取N行

https://serverfault.com/questions/490841/how-to-display-the-first-n-lines-of-a-command-output-in-windows-the-equivalent

powershell获取文件的第一个x MB

https://superuser.com/questions/859870/windows-equivalent-of-the-head-c-command

alr*_*roc 51

如果您有PowerShell 3或更高版本,则可以使用-Tail参数Get-Content来获取最后n一行.

Get-content -tail 5 PATH_TO_FILE;
Run Code Online (Sandbox Code Playgroud)

在我本地SSD上的34MB文本文件中,这在1毫秒内返回,而在8.5秒内则返回 get-content |select -last 5

  • 我不为一家软件公司工作.没有PS3并不是需要去其他地方的症状(即使它很方便!).这是我的看法.谢谢你的生动! (5认同)
  • 抱歉,如果一个被认为是核心Windows组件的软件在发布后的三年多内没有考虑进行升级,我认为环境已经破碎.还有什么是过时的,甚至更糟糕的是,未修补安全性和错误修复?当你背负过时的软件时,你能在多大程度上提升自己的职业和技术知识?*那就是你继续前进的原因 - 因为你无法在这样的环境中提高自己的技能. (3认同)

Azi*_*hev 15

怎么样(读取最后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()
}
Run Code Online (Sandbox Code Playgroud)

更新.要将字节解释为字符串(但一定要选择正确的编码 - 这里使用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)
Run Code Online (Sandbox Code Playgroud)

更新2.要读取最后M行,我们将按部分读取文件,直到结果中有超过M个换行符char序列:

$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
Run Code Online (Sandbox Code Playgroud)

尝试使用更大的$buffer_size- 这理想地等于预期的平均线路长度,以减少磁盘操作.还要注意$ seq - 这可能是\r\n或者只是\n.这是非常脏的代码,没有任何错误处理和优化.


Pet*_*cek 7

当文件已经打开时,最好使用

Get-Content $fpath -tail 10
Run Code Online (Sandbox Code Playgroud)

因为“使用“1”个参数调用“OpenRead”时出现异常:“该进程无法访问该文件...”