[[20220112160519]] 『バイナリデータを読み込み、特定文字列を置換』(motimoti) >>BOT

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『バイナリデータを読み込み、特定文字列を置換』(motimoti)

お世話になります

VBAでバイナリデータを読み込み、特定文字列を置換して別ファイルに格納したいと考えております。

http://www.cocoaliz.com/excelVBA/index.php/47/
こちらを参考に、データをbyte型にできたのですが、
特定文字列を置換するところで詰まっています。
byte型の扱いは慣れてないもので・・・

バイナリデータにSJISの文字列が入ってるので、
そこをうまくstrconvなど使ってReplaceできればと考えていますが、
うまくいきません。
どのようにしたら良いでしょうか。

よろしくお願いいたします。

< 使用 Excel:Excel2013、使用 OS:Windows10 >


>バイナリデータにSJISの文字列が入ってるので、

データの例を示していただかないと、イメージできません。

(わからん) 2022/01/12(水) 16:17


 Byte型配列と文字列型は互いに可換です。
 >SJISの文字列が入ってるので
 VBAは古いのでファイル入出力はSJISです。そのまま取り扱いできます。

 Sub sample()
  Dim buf() As Byte
  buf = "あいうえお"
  Debug.Print buf
  buf = Replace(buf, "い", "か")
  Debug.Print buf
 End Sub
(´・ω・`) 2022/01/12(水) 16:37

わからんさん

例えば
sjisの"ABC"という文字列を"DEF"に置換したい

41 42 43 (ABC)

44 45 46 (DEF)

このような感じです

´・ω・`さん
ありがとうございます。
サンプルは動いたのですが、
実際のファイルではうまく動きませんでした。

もしかするとデータ「00」で置換が終わってしまうのでしょうか。
バイナリデータを見た感じだと、00が多く入っているのですが、
解決策ありますでしょうか

よろしくお願いいたします。
(motimoti) 2022/01/12(水) 17:01


 文字列型ではないバイト列に対して置換かけたら結果は保証されません
 例えば、整数や浮動小数点数のバイト列に、偶然に文字として解釈できるデータがあったら
 まずいことになります。

 バイナリファイルの仕様をちゃんと見て、文字列データに対してだけ置換するような
 コードを書かないといけません
(´・ω・`) 2022/01/12(水) 17:32

>41 42 43 (ABC)

他の部分との見分け方を知りたいのですが...

「41 42 43」と並んでいるデータを無差別に置換していいのでしょうか?
あと、2バイト文字(漢字とか)は含まれていないのですか?

(かぶってますね..)
(わからん) 2022/01/12(水) 17:36


´・ω・`さん
わからんさん

2バイト文字もありますが、
検索される文字列(ABCの部分)は、絶対に重複しないようなデータ列になっていますので、
今回は考慮しなくてOKです。

よろしくお願いいたします。
(motimoti) 2022/01/12(水) 17:52


 ごめんなさい
 訂正です。

 ファイルからSJISの文字列をGetするとに、文字列型で読まないとだめですね。
 Byte型配列でよむとうまくいきません。
 Byte型配列で読んだ後→文字列型変数に代入→置換→Byte型配列に代入→ファイルに書き込み

 としないといけないようです。この辺ちょっと確認不足で回答してしましました。

 あと、バイナリデータなのに、
 >絶対に重複しないようなデータ列
 だと断言できるというのは信じられません
(´・ω・`) 2022/01/12(水) 18:34

>考慮しなくてOKです。
そうなんですね。

ところで、データのサイズはどの程度なのでしょうか。
データの先頭から、地道に比較していくのもありかなと思ったので。

(わからん) 2022/01/12(水) 20:04


回答ありがとうございます。

´・ω・`さん

string型変数に代入したのですが、
vbaの内部でunicode?で扱われるのか、
はたまた00データを終端として認識するのかわかりませんが、
置換ができていませんでした。

バイナリデータについてですが、
検索文字列は、こちらで設定できる部分で、
バイナリエディタで重複していないことを確認しています。

わからんさん

データのサイズは30KB程度です。
replaceで楽しようとしてました。
やはり地道に比較するしかないのでしょうかね
(motimoti) 2022/01/14(金) 10:19


>データの先頭から、地道に比較していくのもありかな

地道に比較する方法で実用的な速度が得られるかテスト用に作成しました。
120KBのデータで試しましたが、実用的には問題ない速度でした。
(2バイト文字には対応していませんし、いろいろと手抜きですが...)

 Sub replace_binary()
    Dim buf() As Byte
    Dim a1() As Byte    '置換前文字列
    Dim a2() As Byte    '置換後文字列

    s1 = "ABCDEFG"
    ReDim a1(Len(s1))
    For i = 0 To Len(s1) - 1
        a1(i) = Asc(Mid(s1, i + 1, 1))
    Next

    s2 = "JKLMNOP"
    ReDim a2(Len(s2))
    For i = 0 To Len(s2) - 1
        a2(i) = Asc(Mid(s2, i + 1, 1))
    Next

    p = "C:\Users\XXXX\Desktop\"   'バイナリファイルパス
    Open p & "Test.bin" For Binary As #1

    ReDim buf(LOF(1))
    Get #1, , buf
    Close

    For i = 0 To UBound(buf)
        found = True
        For j = 0 To UBound(a1) - 1
            If buf(i + j) <> a1(j) Then
                found = False
                Exit For
            End If
        Next
        If found Then
            MsgBox "見つかりました。" & vbCrLf & s1 & "(" & i & ")"
            '置換処理
            For j = 0 To UBound(a1) - 1
                buf(i + j) = a2(j)
            Next
        End If
    Next

    '書込処理
    Open p & "Test.bin" For Binary As #1
    Put #1, , buf
    Close
 End Sub

(わからん) 2022/01/14(金) 16:13


わからんさん

長いこと返信できませんでしたが、ありがとうございます。

とりあえず1個ずつ比較する方法で置換できるようになりました。
ありがとうございました!
(motimoti) 2022/01/19(水) 10:55


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.