Найти последнее вхождение байта ASCII в файле и обрезать файл от этой точки до конца? - PullRequest
0 голосов
/ 02 декабря 2018

В среде командной строки Windows, я хотел бы иметь возможность искать двоичный файл для последнего (последнего) вхождения шестнадцатеричного символа 06 («Ack») и обрезать файл от этого символа до концафайл, означающий, что найденный символ также обрезается.Как я могу это сделать?Размер файлов может составлять несколько сотен мегабайт.

РЕДАКТИРОВАТЬ: Честно говоря, я довольно много гуглил для идей кода, но мои поисковые термины не привели меня к каким-то способам решения этой проблемы.Что-то вроде «поиск двоичного файла для ASCII char hex 06, поиск последнего вхождения этого символа и усечение файла с этого момента» настолько расплывчато, что по сути бесполезно.Я буду продолжать искать!

1 Ответ

0 голосов
/ 02 декабря 2018

Если вы начнете читать байты с конца файла, вы найдете последний ACK (если он есть).Зная его положение, теперь вы можете обрезать файл.

Я не очень силен в PowerShell, поэтому может быть какой-то командлет, о котором я не знаю, но это позволяет достичь того, чего вы хотите:

$filename = "C:\temp\FindAck.txt"
$file = Get-Item $filename
$len = $file.Length
$blockSize = 32768
$buffer = new-object byte[] $blockSize

$found = $false
$blockNum = [math]::floor($len / $blockSize)

$mode = [System.IO.FileMode]::Open
$access = [System.IO.FileAccess]::Read
$sharing = [IO.FileShare]::Read
$fs = New-Object IO.FileStream($filename, $mode, $access, $sharing)

$foundPos = -1

while (!$found -and $blockNum -ge 0) {
    $fs.Position = $blockNum * $blockSize
    $bytesRead = $fs.Read($buffer, 0, $blocksize)
    if ($bytesRead -gt 0) {
        for ($i = $bytesRead -1; $i -ge 0; $i--) {
            if ($buffer[$i] -eq 6) {
                $foundPos = $blockNum * $blockSize + $i
                $found = $true
                break
            }
        }
    }
    $blockNum--
}

$fs.Dispose()

if ($foundPos -ne -1) {
    $mode = [System.IO.FileMode]::Open
    $access = [System.IO.FileAccess]::Write
    $sharing = [IO.FileShare]::Read

    $fs = New-Object IO.FileStream($filename, $mode, $access, $sharing)
    $fs.SetLength($foundPos)
    $fs.Dispose()
}

Write-Host $foundPos

Идея чтения в блоках по 32 КБ состоит в том, чтобы получить разумный размер блока с диска для обработки, а не читать по одному байту за раз.


Ссылки:

...