C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: バイナリファイルから文字置換ファイル出力


(過去ログ 123 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■73515 / inTopicNo.1)  バイナリファイルから文字置換ファイル出力
  
□投稿者/ じっちゃん (3回)-(2014/10/06(Mon) 12:35:48)

分類:[VB.NET/VB2005 以降] 

バイナリファイルから指定の文字を検索して文字を入換えてファイル書き出ししたい。
現在バイナリエディタで、その文字を検索して、書換後ファイル書き出ししています。
その処理をVB.NETでやりたいと考えていますが、バイナリファイルを扱った事が無い為に、
どの様なコマンドを書いていいかも分かりません。
下のコードを入手して、ファイルコピーが出来る事は確認出来ました。
readSize = src.Read(buf, 0, BUFSIZE) 部分の
bufを検索して、合致すれば、入換て書き出せばいいと思ってます。
検索方法と入換方がわかりません。

やりたいのは、ABC(41 42 43)の文字を検索して(ファイルには一箇所しか無い物とします。)、
DATA(44 41 54 41)に書換えてファイル出力する。
と言う事です。ファイルサイズは大きくはありません。
バッファのサイズを
Dim BUFSIZE As Integer = 2048で指定出来ますが。
これを数倍にして、一回で読み込める物とします。(数回に分けられると、継ぎ目が発生して
なんか大変そうな感じしますので。)
すみませんが、検索、入換方法の概略だけでも宜しくお願い致します。

Sub main_x(ByVal args As String())
Dim srcName As String = args(0) ' コピー元のファイル名
Dim destName As String = args(1) ' コピー先のファイル名
Dim BUFSIZE As Integer = 2048 '2048 ' 1度に処理するサイズ
Dim buf(BUFSIZE) As Byte ' 読み込み用バッファ
Dim ZEROARRAY(BUFSIZE) As Byte ' 0埋め用
Dim readSize As Integer ' Readメソッドで読み込んだバイト数
Using src As New FileStream( _
srcName, FileMode.Open, FileAccess.Read)
Using dest As New FileStream( _
destName, FileMode.Create, FileAccess.Write)
While True
readSize = src.Read(buf, 0, BUFSIZE) ' 読み込み
If readSize = 0 Then
Exit While ' コピー完了
End If
dest.Write(buf, 0, readSize) ' 書き込み
End While
End Using
End Using
End Sub
引用返信 編集キー/
■73518 / inTopicNo.2)  Re[1]: バイナリファイルから文字置換ファイル出力
□投稿者/ 魔界の仮面弁士 (132回)-(2014/10/06(Mon) 13:36:08)
No73515 (じっちゃん さん) に返信
> バイナリファイルから指定の文字を検索して文字を入換えてファイル書き出ししたい。

その前に、仕様を確認させてください。

そのファイルに含まれているのは、テキストデータだけですか?
それとも、文字以外のバイナリ情報も含んでいますか?


> やりたいのは、ABC(41 42 43)の文字を検索して(ファイルには一箇所しか無い物とします。)、
> DATA(44 41 54 41)に書換えてファイル出力する。

たとえば 44 41 54 41 という 4 バイトのバイナリは、
「文字列」としては "DATA" ですが、
「4 バイト整数値」としてみれば 1,096,040,772 という
値であるとみなすこともできます。


もし、テキストデータ以外も含んでいるファイルなのだとしたら、
置換する場所によっては、文字部以外のデータを破壊してしまう可能性も
考えられますが、その点はどのように対策されるのでしょうか?


もう一つ。
そのファイル内で使われている文字列は、何でエンコードされていますか?

Shift_JIS の場合、ファイル内の「文字列の先頭位置」が分からないと
正しく検索・置換できません。

たとえば、下記の Shift_JIS 文字列が並んでいた場合、
「≠」のつもりで [81 82] を検索したはずが、
文字と文字の境目に合致してしまうかも知れません。

 = (81 81)
 ≠ (81 82)
 a (82 81)
 b (82 82)


UTF-8 ならば、先導バイトと後続バイトを確実に区別できますが、
Shift_JIS の場合は、先導バイトにも後続バイトにもなれるバイナリ値が
ありえます。ファイル中のどこからどこまでがバイナリデータで、
どの部分が可読文字領域なのか、フォーマットを明確にしておいた方が良いでしょう。
引用返信 編集キー/
■73519 / inTopicNo.3)  Re[1]: バイナリファイルから文字置換ファイル出力
□投稿者/ しま (87回)-(2014/10/06(Mon) 13:51:12)
No73515 (じっちゃん さん) に返信
> バイナリファイルから指定の文字を検索して文字を入換えてファイル書き出ししたい。
> 現在バイナリエディタで、その文字を検索して、書換後ファイル書き出ししています。
> その処理をVB.NETでやりたいと考えていますが、バイナリファイルを扱った事が無い為に、
> どの様なコマンドを書いていいかも分かりません。
> 下のコードを入手して、ファイルコピーが出来る事は確認出来ました。
> readSize = src.Read(buf, 0, BUFSIZE) 部分の
> bufを検索して、合致すれば、入換て書き出せばいいと思ってます。
> 検索方法と入換方がわかりません。
>
> やりたいのは、ABC(41 42 43)の文字を検索して(ファイルには一箇所しか無い物とします。)、
> DATA(44 41 54 41)に書換えてファイル出力する。
> と言う事です。ファイルサイズは大きくはありません。

プログラムのコードを貼るときは「投稿モード」の『図表モード』を選んで下さい。
バイト配列中の値を検索する例は
http://www.my-hobby.jp/index.php/2012/01/vb-net2/

を見てもらうとして、編集の方法は初心者向きの判り易いと思われる、出力用にバイト配列をもう一つ用意して
読込んだ入力の配列からデーターを必要なだけコピーする方法はいかがでしょうか?
たかだか数Kバイトほどのデーター量なので1バイトずつコピーしてもそれほど時間が掛かるとは思えません。
見つけたら、手前までを出力用の配列にコピーして、 DATA{44,41,54,41} とそれに続けて出力用配列に書き込んで、
その後に残りの部分をコピーすればよろしいかと思います。

他には、入力配列から探したい値の並びを探して、見つけたら見つかる手前までの内容をファイルに書出して、
書替えたい値の列は検索用にあるのだから、その検索用の配列の内容をファイルに書出して、
次に、見つけた値の並びの次から(見つけた場所から探したいデーターの長さ分後ろに下がった位置から)ファイルに書出すのは簡単でしょうか?
引用返信 編集キー/
■73520 / inTopicNo.4)  Re[1]: バイナリファイルから文字置換ファイル出力
□投稿者/ 魔界の仮面弁士 (133回)-(2014/10/06(Mon) 15:18:32)
No73515 (じっちゃん さん) に返信
> やりたいのは、ABC(41 42 43)の文字を検索して(ファイルには一箇所しか無い物とします。)、
> DATA(44 41 54 41)に書換えてファイル出力する。

手抜き実装:

Module Module1
    Sub Main()
        Dim srcFilePath = "C:\temp\test.txt"
        Dim dstFilePath = "C:\temp\test2.txt"

        Dim 捜索データ() As Byte = {&H41, &H42, &H43}
        Dim 置換データ() As Byte = {&H44, &H41, &H54, &H41}

        Dim 捜索長さ As Integer = 捜索データ.Length

        Dim 元バイナリ() As Byte = System.IO.File.ReadAllBytes(srcFilePath)
        Dim q = 元バイナリ.TakeWhile(Function(b, i) Not 元バイナリ.Skip(i).Take(捜索長さ).SequenceEqual(捜索データ)).ToArray()
        If q.Length < 元バイナリ.Length Then
            Dim 置換結果 = q.Concat(置換データ).Concat(元バイナリ.Skip(q.Length + 捜索長さ))
            System.IO.File.WriteAllBytes(dstFilePath, 置換結果.ToArray())
            Console.WriteLine("置換しました。")
        Else
            System.IO.File.WriteAllBytes(dstFilePath, 元バイナリ)
            Console.WriteLine("見つかりませんでした。")
        End If
    End Sub
End Module

引用返信 編集キー/
■73525 / inTopicNo.5)  Re[2]: バイナリファイルから文字置換ファイル出力
□投稿者/ じっちゃん (4回)-(2014/10/06(Mon) 21:23:01)
魔界の仮面弁士さん
大変有り難う御座います。
ファイルには、文字以外のバイナリ情報も含んでいます。
ファイル内で使われている文字列は、Shift_JISでエンコードされているようです。
ご指摘の事が発生するかも知れませんね。

提示頂いたコードで置換出来ている事が確認出来ました。
今回エディタを使用していて、手操作していた物を簡単にしようと言うことで
始めています。その後確認操作をするので、シンプルでかまいません。

しま さん
大変有り難う御座います。
教えて頂いた バイト配列中の値を検索する例を実行して配列に取得したデータが
入ってる事が確認出来ました。

とりあえずは、魔界の仮面弁士さんのコードで変換出来ましたので、
解決とさせて頂きます。ありがとうございました。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -