バイナリデータを検索する方法(vb.net)

画像データなどのバイナリ化されたデータから特定の16進コードを検索する方法を紹介します。
今回のケースは、下記の様なバイナリデータから、「my-hobby」という文字列を含み、かつ「my-hobby」の後に「&HFF」(16進コードFF)が付くバイナリデータの最初のインデックスを取得する方法です。

検索対象とするバイナリデータの情報は下記の通りです。

上記の赤枠部分が今回検索したい箇所です。

ソースは下記の通り
[vbnet]
Imports System.IO

Dim ByteArray As Byte()
Dim TargetByte As Byte() = {&H6D, &H79, &H2D, &H68, &H6F, &H62, &H62, &H79, &HFF} ‘「my-hobby」を16進化したコードをセット(最後はFF)
Dim i As Integer
Dim ByteIndex As Integer
Dim StartIndex As Integer
Dim HitFLG As Boolean ‘True:検索文字列ヒット

ByteArray = File.ReadAllBytes(ファイルパス) ‘.net Framework 2.0以上対応
StartIndex = 0

Do
ByteIndex = Array.IndexOf(ByteArray, TargetByte(0), StartIndex) ‘最初の一文字を検索する
If ByteIndex < 0 Or StartIndex + TargetByte.Length – 1 >= ByteArray.Length Then
ByteIndex = -1
HitFLG = False
Exit Do ‘最初の文字が見つからなかった場合、またはStartIndexの位置がバイト配列の最後まで到達した場合は処理終了
Else
HitFLG = True ‘一時的にヒットの状態にする
End If

For i = 1 To TargetByte.Length – 1 ‘残りの文字(2文字目以降)も検索する
If ByteArray(ByteIndex + i) <> TargetByte(i) Then
HitFLG = False ‘1文字でも合致しなかったらFalseにセット
Exit For
End If
Next

If HitFLG = True Then
Exit Do ‘全ての文字がヒットしたら処理を抜ける
Else
StartIndex = ByteIndex + 1 ‘ヒットしなかった場合は、検索開始位置を1バイトずらして再度検索
End If
Loop

Console.Write(ByteIndex) ‘該当した文字列の1文字目の配列インデックスを出力する。-1の場合は該当する文字が無かった事を意味する。
[/vbnet]

上記の処理を実行すると、272 が出力されます。
なお、上記処理はInteger型の上限を超える容量のファイルを扱う事は出来ません。

ちなみに上記の検索アルゴリズムはクヌース-モリス-プラット法 – Wikipediaという方式に似ていますが、バイナリデータの保存形式、使用用途に応じて検索アルゴリズムを変えていく事で、より高速な検索が出来るのでは無いかと思います。
Category:検索アルゴリズム – Wikipediaを見ると、世の中には色んな検索アルゴリズムがある事が分かります。

まぁこの辺を意識しなくても検索できる、.net Frameworkが出来てくれると一番嬉しいんですが。。。

カテゴリー: VB.NET パーマリンク

バイナリデータを検索する方法(vb.net) への1件のフィードバック

  1. ひばら みつひろ のコメント:

    勝手ながら、自身のブログ記事からリンクを張らせていただきました。
    https://hibara.org/blog/2016/08/22/c-sharp-binary-search/
    よろしくお願いいたします。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です