こんにちは!エンジニアリングの世界へようこそ。
マクロの記録や簡単なスクリプトの実行から一歩進んで、「自分だけのしっかりとしたアプリケーションを作りたい!」そう思っている時期が一番ワクワクしますよね。
今回は、VB.NETを使った「BinaryReaderとBinaryWriterによる独自バイナリファイルフォーマットの読み書き」について解説していきます。
「バイナリファイル?なんだか難しそう……」と思ったかもしれませんが、大丈夫です。ここをクリアすれば、データ構造を完全にコントロールできるようになり、あなたのプログラムの可能性はグッと広がります。基礎から本質まで優しく噛み砕いてお伝えしますので、ぜひ最後までついてきてくださいね。
—
1. なぜテキスト(CSV)ではなく「バイナリ」なのか?
私たちが普段よく使うCSVファイルやテキストファイルは、人間がメモ帳で中身を読めるので便利です。しかし、次のようなデメリットもあります。
- ファイルサイズが大きくなりがち(数値をわざわざ文字に変換しているため)。
- 読み書きのたびに文字コードの変換やパース(解析)が発生し、処理が遅い。
- データ構造をそのまま隠蔽しにくいため、改ざんや丸見えのリスクがある。
これに対して、今回学ぶバイナリファイルは、メモリ上のデータをそのまま(あるいはそれに近い形で)ファイルに書き出す仕組みです。そのため、「超高速」「省スペース」「独自のセキュリティ(フォーマット)」という強力なメリットを手に入れることができます。
—
2. 秘密の設計図:バイナリフォーマットの構造を決めよう
バイナリファイルを読み書きするには、あらかじめ「ファイルの何バイト目に、どんなデータが、どんな順番で並んでいるか」という設計図(仕様)を決める必要があります。
今回は、初心者の方でも理解しやすいように、以下のようなシンプルな「プレイヤーセーブデータ」を例にしましょう。
1. ヘッダー識別子(文字3文字:「RPG」) -> データの正当性を確認するため
2. プレイヤーレベル(整数:Integer / 4バイト)
3. 所持金(長整数:Long / 8バイト)
4. プレイヤー名(文字列:String / 可変長)
このデータを、`BinaryWriter`を使って書き込み、`BinaryReader`で正確に読み出すコードを書いていきます。
—
3. 実装コード:書き込みと読み込みの全貌
それでは、VB.NETのコンソールアプリケーションやWindowsフォームなどでそのまま動かせる実用的なコードを見てみましょう。
Imports System.IO
Module BinaryFileSample
‘ 保存するファイルのパス
Private Const FilePath As String = “player_data.dat”
Sub Main()
‘ 1. データの書き込み(シリアライズ)
Console.WriteLine(“— データをバイナリファイルに書き込みます —“)
WriteBinaryData(FilePath)
‘ 2. データの読み込み(デシリアライズ)
Console.WriteLine(vbCrLf & “— バイナリファイルからデータを読み込みます —“)
ReadBinaryData(FilePath)
Console.WriteLine(vbCrLf & “処理が完了しました。何かキーを押してください…”)
Console.ReadKey()
End Sub
”’
”’
Sub WriteBinaryData(path As String)
‘ Usingブロックを使うことで、ファイルストリームの解放漏れを防ぎます(メモリ管理の鉄則!)
Using fs As New FileStream(path, FileMode.Create, FileAccess.Write),
writer As New BinaryWriter(fs)
‘ 書き込むデータ
Dim headerCode As String = “RPG”
Dim level As Integer = 42
Dim gold As Long = 1250000L
Dim playerName As String = “ロトの勇者”
‘ 順番に書き込んでいく(これがそのままファイルの構造になります)
writer.Write(headerCode.ToCharArray()) ‘ 文字配列として3文字書き込む
writer.Write(level) ‘ 4バイトの整数
writer.Write(gold) ‘ 8バイトの長整数
writer.Write(playerName) ‘ 文字列(内部で長さ情報も一緒に書き込まれます)
Console.WriteLine(“書き込み成功: レベル={0}, 所持金={1}, 名前={2}”, level, gold, playerName)
End Using
End Sub
”’
”’
Sub ReadBinaryData(path As String)
If Not File.Exists(path) Then
Console.WriteLine(“ファイルが見つかりません。”)
Return
End If
Using fs As New FileStream(path, FileMode.Open, FileAccess.Read),
reader As New BinaryReader(fs)
‘ 1. ヘッダーの読み込み(3文字分を配列で受け取る)
Dim headerChars(2) As Char
reader.Read(headerChars, 0, 3)
Dim headerCode As New String(headerChars)
‘ 識別子のチェック(不正なファイルでないか確認する防衛的プログラミング)
If headerCode <> “RPG” Then
Console.WriteLine(“エラー: 未知のファイルフォーマットです。”)
Return
End If
‘ 2. データの読み込み(書いた時と「全く同じ順番・型」で読むのが鉄則!)
Dim level As Integer = reader.ReadInt32()
Dim gold As Long = reader.ReadInt64()
Dim playerName As String = reader.ReadString()
‘ 読み込んだ結果を表示
Console.WriteLine(“読み込み成功!”)
Console.WriteLine(” ヘッダー: {0}”, headerCode)
Console.WriteLine(” レベル: {0}”, level)
Console.WriteLine(” 所持金: {0} Gold”, gold)
Console.WriteLine(” 名前: {0}”, playerName)
End Using
End Sub
End Module
—
4. コードの重要ポイントと「陥りやすい罠」
ここからは、プロのエンジニアとして知っておくべき「本質的な注意点」を解説します。ここを理解しておくと、現場でバグに悩まされなくなりますよ。
① 「書いた順・型」でしか読めないという厳格さ
`BinaryWriter`で `Integer` を書いたなら、読むときは必ず `BinaryReader.ReadInt32()` で読まなければなりません。
もし順番を間違えたり、途中で `Integer`(4バイト)を読むべきところで `Long`(8バイト)を読んでしまうと、データのズレ(バイトシフト)が発生し、ファイル全体がゴミデータになってしまいます。バイナリの世界は「順番と型が命」です。
② `Using` ステートメントによるリソース解放
ファイルやネットワークなどの外部リソースを扱う際、使い終わったら必ず閉じる(開放する)必要があります。
VB.NETの `Using` を使えば、万が一エラーが発生して処理が途中で止まったとしても、自動的に安全にファイルを閉じてメモリリークを防いでくれます。これは実務では絶対の常識です。
③ 文字列の扱い(エンコーディングと長さに注意)
`BinaryWriter.Write(String)` を使うと、.NETの仕様で「文字列の長さ(バイト数または文字数)」が自動的に文字列の先頭に付与されて保存されます。
もし「他の言語(C++やPythonなど)で作られたバイナリファイル」をVB.NETで読みたい場合などは、文字の長さがどのように格納されているか(プレフィックスがあるかないか)に細心の注意を払う必要があります。
—
おわりに
お疲れ様でした!
`BinaryReader` と `BinaryWriter` を使ったバイナリファイルの読み書き、いかがでしたでしょうか?
一見難しそうに見えるバイナリ操作も、「ファイルという一本の道路に対して、決まったサイズと順番で荷物を積み下ろしているだけ」とイメージできれば、怖くありませんよね。
ここをクリアできたあなたなら、独自のセーブデータ形式、高速なキャッシュファイル、さらには独自の暗号化フォーマットの作成まで、どんなデータ処理でも自由自在です。
Visual Basic (VB / VB.NET) の基本はこれでバッチリです!自信を持って次のステップへ進んでくださいね。応援しています!
