移动二进制数据直到特定值从一个文件到另一个文件

Move binary data until specific values from one file to another

我编写了一个 Visual Basic 应用程序并卡在了一点:
我需要该应用程序读取文件,select DDS 字符串之前的所有内容,将其从文件中剪切并粘贴到新文件中。

然后在编辑 DDS 后插入 header。

问题是,这个 header 在 DDS 之前没有固定长度:每个这种类型的文件都有不同的 header。我试图弄乱 System.IO.FileStream 但没有结果。

这甚至可以做到吗?

header 长度不多,一个简单的搜索模式可能就足够了。

将要在文件中查找的字节序列和文件路径传递给 FindHeader 方法。
它 returns 一个字节数组,包含在找到指定序列之前收集的所有字节。

这是一个简单的模式匹配,向前查找直到找到可以匹配指定序列的第一个字节。
然后它读取缓冲区并将缓冲区与序列进行比较:
- 如果匹配,returns 到该点为止累积的字节数;
- 如果不是,它从 [Sequence Length] - 1 个位置的当前位置(在当前 Stream 缓冲区内)回溯并继续。

你可以这样称呼它:

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

现在我们有了第一个源文件的Header。

那么第二个源文件的数据部分是:

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

我们需要创建第三个文件,它将包含第一个文件的 Header 和从第二个文件读取的数据。

' 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 objects,我们创建一个新的Destination File,写入第一个Source File的header,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

Headerreader方法:

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