Перемещать двоичные данные до тех пор, пока не будут заданы значения c из одного файла в другой - PullRequest
0 голосов
/ 11 апреля 2020

Я пишу приложение Visual Basi c и застрял в одной точке:
Мне нужно, чтобы это приложение прочитало файл, выделило все перед строкой DDS, вырезало его из файла и вставило в новый файл.

image

Затем после редактирования DDS вставьте этот заголовок.

Проблема в том, что этот заголовок до DDS не имеет фиксированной длины: каждый файл этого типа имеет свой заголовок. Я пытался связываться с System.IO.FileStream, но не получил результата.

Это вообще возможно сделать?

1 Ответ

0 голосов
/ 12 апреля 2020

Длина заголовка не так уж и велика, вероятно, достаточно простого шаблона поиска.

Передайте последовательность байтов, чтобы найти внутри файла и путь к файлу метод FindHeader.
Возвращает байтовый массив, содержащий все байты, собранные до указанной последовательности найден.

Это простое сопоставление с шаблоном, которое ищет вперед, пока не найдет первый байт, который может соответствовать указанной последовательности.
Затем он читает буфер и сравнивает буфер с последовательностью:
- если это совпадение, возвращает байты, накопленные до этой точки;
- если это не так, он возвращается с текущей позиции на [Sequence Length] - 1 позиции (внутри текущего буфера потока) и продолжается.

Вы можете назвать это так:

Dim closeSequence = New Byte() { &H44, &H44, &H53 }
Dim headerBytes = FindHeader([Source File 1 Path], closeSequence)

Теперь у нас есть заголовок первого исходного файла.

Тогда раздел данных второго исходного файла:

Dim sourceFile2DataStart = FindHeader([Source File 2 Path], closeSequence).Length + closeSequence.Length
Dim dataLength = New FileInfo([Source File 2 Path]).Length - sourceFile2DataStart

Нам нужно создать третий файл, который будет содержать заголовок первого файла и данные, считанные из второго файла. ,

' Create a read buffer. The buffer length is less than or equal to the data length
Dim bufferLength As Integer = CInt(If(dataLength >= 1024, 1024, dataLength))
Dim buffer As Byte() = New Byte(bufferLength - 1) {}
Dim read As Integer = 0

Используя два объекта FileStream, мы создаем новый файл назначения, записываем заголовок первого исходного файла, closeSequence, который идентифицирует начало раздела данных, затем мы читаем буфер из второго исходного файла и записываем буфер в файл назначения:

Dim patchworkFilePath as string = [Path of the Destination File]

Using sWriter As FileStream = New FileStream(patchworkFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None),
    sReader As FileStream = New FileStream([Source File 2 Path], FileMode.Open, FileAccess.Read, FileShare.None)
    sReader.Seek(sourceFile2DataStart, SeekOrigin.Begin)
    sWriter.Write(header1Bytes, 0, header1Bytes.Length)
    sWriter.Write(closeSequence, 0, closeSequence.Length)

    While True
        read = sReader.Read(buffer, 0, buffer.Length)
        If read = 0 Then Exit While
        sWriter.Write(buffer, 0, read)
    End While
End Using

Метод чтения заголовка:

Public Function FindHeader(filePath As String, headerClosure As Byte()) As Byte()
    Dim byteToFind = headerClosure(0)
    Dim buffer = New Byte(headerClosure.Length - 1) {}
    Dim header = New List(Of Byte)(2048)
    Dim read As Integer = 0

    Using fs As FileStream = New FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None)
        While fs.Position <= (fs.Length - headerClosure.Length)
            read = fs.ReadByte()
            If read = byteToFind Then
                fs.Read(buffer, 1, buffer.Length - 1)
                buffer(0) = CByte(read)
                If buffer.SequenceEqual(headerClosure) Then Exit While
                fs.Seek(-(buffer.Length - 1), SeekOrigin.Current)
            End If
            header.Add(CByte(read))
        End While
    End Using
    Return header.ToArray()
End Function
...