[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『バイナリデータを読み込み、特定文字列を置換』(motimoti)
お世話になります
VBAでバイナリデータを読み込み、特定文字列を置換して別ファイルに格納したいと考えております。
http://www.cocoaliz.com/excelVBA/index.php/47/
こちらを参考に、データをbyte型にできたのですが、
特定文字列を置換するところで詰まっています。
byte型の扱いは慣れてないもので・・・
バイナリデータにSJISの文字列が入ってるので、
そこをうまくstrconvなど使ってReplaceできればと考えていますが、
うまくいきません。
どのようにしたら良いでしょうか。
よろしくお願いいたします。
< 使用 Excel:Excel2013、使用 OS:Windows10 >
データの例を示していただかないと、イメージできません。
(わからん) 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」と並んでいるデータを無差別に置換していいのでしょうか?
あと、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
ところで、データのサイズはどの程度なのでしょうか。
データの先頭から、地道に比較していくのもありかなと思ったので。
(わからん) 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.