Регулярный поиск в двоичном файле

Я пытаюсь написать сценарий Excel VBA, который извлекает некоторую информацию (версию и дату редакции) из двоичного файла FrameMaker (*.fm).

Следующая подпрограмма открывает файл *.fm и записывает первые 25 строк (необходимая информация в эти первые 25 строк) в переменную.

Sub fetchDate()
    Dim fso As Object
    Dim fmFile As Object

    Dim fileString As String
    Dim fileName As String
    Dim matchPattern As String
    Dim result As String
    Dim i As Integer
    Dim bufferString As String

    Set fso = CreateObject("Scripting.FileSystemObject")

    fileName = "C:\FrameMaker-file.fm"

    Set fmFile = fso.OpenTextFile(fileName, ForReading, False, TristateFalse)
    matchPattern = "Version - Date.+?(\d{1,2})[\s\S]*Rev.+?(\d{1,2})"

    fileString = ""
    i = 1
    Do While i <= 25
        bufferString = fmFile.ReadLine
        fileString = fileString & bufferString & vbNewLine
        i = i + 1
    Loop
    fmFile.Close

    'fileString = Replace(fileString, matchPattern, "")
    result = regExSearch(fileString, matchPattern)

    MsgBox result

    Set fso = Nothing
    Set fmFile = Nothing
End Sub

Функции регулярных выражений выглядят так:

Function regExSearch(ByVal strInput As String, ByVal strPattern As String) As String
    Dim regEx As New RegExp

    Dim strReplace As String
    Dim result As String
    Dim match As Variant
    Dim matches As Variant
    Dim subMatch As Variant

    Set regEx = CreateObject("VBScript.RegExp")

    If strPattern <> "" Then
        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = strPattern
        End With

        If regEx.test(strInput) Then
            Set matches = regEx.Execute(strPattern)

            For Each match In matches
                If match.SubMatches.Count > 0 Then
                    For Each subMatch In match.SubMatches
                        Debug.Print "match:" & subMatch
                    Next subMatch
                End If
            Next match

            regExSearch = result
        Else
            regExSearch = "no match"
        End If
    End If

    Set regEx = Nothing
End Function

Проблема 1:

Содержимое двоичного файла *.fm, который сохраняется в переменной "fileString", отличается при каждом запуске, хотя файл *.fm остается неизменным.

Вот несколько примеров первых трех строк из разных прогонов, которые сохранены в "fileString":

пример 1

<MakerFile 12.0>


Aaÿ No.009.xxx  ????          /tEXt     ??????

пример 2

<MakerFile 12.0>


Aaÿ  `      ? ????          /tEXt ?     c ? E     ? ????a A ? ?      ? ? ? d??????? ?        Heading ????????????A???????A

Как вы видите, пример 1 отличается от примера 2, хотя это был тот же код VBA и тот же файл *.fm.

Проблема 2:

Также большой проблемой является то, что строка поиска регулярных выражений из "matchPattern" записывается случайным образом в мою "fileString". Вот скриншот с консоли отладки:

части значения matchPattern

Как это может быть? Любые предложения или идеи, чтобы решить эту проблему?

Я использую:

MS Office Профессиональный Плюс 2010

Справочник по VBA для регулярных выражений: Регулярные выражения Microsoft VBScript 5.5

Заранее большое спасибо!

С уважением, Энди

/ отредактировать 12 марта 2018 года:

Вот пример файла *.fm: пример файла. Если вы откроете его с помощью блокнота, вы можете увидеть некоторую информацию, такую ​​как "Версия - DateVersion 4 - 2018/ февраль /07" и "Rev02 - 2018/ февраль /21" в виде простого текста. текст. Я хочу получить эту информацию с помощью регулярного выражения.

1 ответ

Решение

Я нашел решение с использованием ADODB.streams. Это отлично работает:

Sub test_binary()
    Dim regEx As Object

    Dim buffer As String
    Dim filename As String
    Dim matchPattern As String
    Dim result As String

    Set regEx = CreateObject("VBScript.RegExp")

    filename = "C:\test.fm"

    With CreateObject("ADODB.Stream")
        .Open
        .Type = 2
        .Charset = "utf-8"
        .LoadFromFile filename
        buffer = .Readtext(10000)
        .Close
    End With

    matchPattern = "Version - Date.+?(\d{1,2})[\s\S]*Rev.+?(\d{1,2})"

    result = regExSearch(buffer, matchPattern)

    MsgBox result
End Sub

функция регулярного выражения:

Function regExSearch(ByVal strInput As String, ByVal strPattern As String) As String
    Dim regEx As New RegExp

    Dim result As String
    Dim match As Variant
    Dim matches As Variant
    Dim subMatch As Variant

    Set regEx = CreateObject("VBScript.RegExp")

    If strPattern <> "" Then
        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = strPattern
        End With

        If regEx.test(strInput) Then
            Set matches = regEx.Execute(strInput)

            result = ""
            For Each match In matches
                If match.SubMatches.Count > 0 Then
                    For Each subMatch In match.SubMatches
                        If Len(result) > 0 Then
                            result = result & "||"
                        End If
                        result = result & subMatch
                    Next subMatch
                End If
            Next match

            regExSearch = result
        Else
            regExSearch = "err_nomatch"
        End If
    End If

    Set regEx = Nothing
End Function

Важно открыть файл *.fm в виде текстового файла (.Type = 2) и установить кодировку "utf-8". В противном случае у меня не будет простого текста для регулярного выражения для чтения.

Большое спасибо за то, что привели меня на правильный путь!

Просто сохраните файл FM как MIF. Это текстовая кодировка FM-файла, которую можно конвертировать туда и обратно без потери информации.

Другие вопросы по тегам