# 機能設計書 31-BinaryWriter

## 概要

本ドキュメントは、VBCorLibライブラリにおけるBinaryWriterクラスの機能設計について記述する。BinaryWriterは、ストリームに対してプリミティブ型のバイナリデータを書き込むためのクラスである。

### 本機能の処理概要

**業務上の目的・背景**：アプリケーションにおいて、設定ファイル、データファイル、またはネットワーク通信において、バイナリ形式でのデータ書き込みが必要となる場面は多い。BinaryWriterは、VB6/VBA環境において.NET Frameworkと互換性のあるバイナリデータ書き込み機能を提供し、プラットフォーム間でのデータ交換を容易にする。特にDecimal型のレイアウトは.NET互換形式に変換されるため、異なるプラットフォーム間でのデータ互換性が確保される。

**機能の利用シーン**：ファイルへのバイナリデータ保存、ネットワークストリームへのデータ送信、メモリストリームを利用したシリアライゼーション処理、設定ファイルやデータファイルのバイナリ形式での保存など、バイナリ形式でデータを永続化または転送する必要があるすべての場面で利用される。

**主要な処理内容**：
1. 各種プリミティブ型（Boolean、Byte、Integer、Long、Single、Double、Currency、Date、Decimal、Int64）のバイナリ書き込み
2. 文字列の長さプレフィックス付きエンコード書き込み（7ビット可変長整数形式）
3. バイト配列およびInteger配列の直接書き込み
4. 単一文字のエンコード書き込み
5. ストリーム位置の制御（SeekPosition）
6. バッファのフラッシュ処理

**関連システム・外部連携**：Streamクラス（FileStream、MemoryStream等）との連携が必須。エンコーディング処理にはEncodingクラス（デフォルトはUTF-8）を使用する。

**権限による制御**：特になし。ただし、基盤となるストリームが書き込み可能である必要がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は画面を持たないライブラリクラスである |

## 機能種別

データ書き込み処理（バイナリI/O）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Output | Stream | Yes | 書き込み先のストリーム | Nothingの場合はArgumentNullException、書き込み不可の場合はArgumentException |
| Encoding | Encoding | No | 文字列エンコーディング（デフォルト: UTF-8） | Nothingの場合はUTF8Encodingを使用 |
| LeaveOpen | Boolean | No | クローズ時にストリームを開いたままにするか | - |
| Value | Variant | Yes | 書き込む値 | 配列の場合はByte配列またはInteger配列のみサポート |
| Index | Variant | No | 配列・文字列の開始位置 | 配列範囲内であること |
| Count | Variant | No | 書き込む要素数 | 配列範囲内であること |

### 入力データソース

プログラムから直接渡されるVariant型の値（プリミティブ型、文字列、バイト配列、Integer配列）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| バイナリデータ | Byte() | ストリームに書き込まれるバイナリデータ |

### 出力先

コンストラクタで指定されたStreamオブジェクト（FileStream、MemoryStream等）

## 処理フロー

### 処理シーケンス

```
1. WriteValue呼び出し
   └─ ストリームがオープンしているか検証
2. 値の型判定
   └─ 配列の場合: WriteArray処理へ
   └─ 非配列の場合: WriteIntrinsic処理へ
3. WriteIntrinsic処理
   └─ 型に応じた書き込みメソッド呼び出し
   └─ バイト配列に変換してストリームへ書き込み
4. 文字列書き込み（WriteString）
   └─ エンコード後のバイト長を7ビット可変長整数で書き込み
   └─ エンコードされたバイト列を書き込み
5. 処理完了
```

### フローチャート

```mermaid
flowchart TD
    A[WriteValue呼び出し] --> B{ストリームオープン?}
    B -->|No| C[ObjectDisposedException]
    B -->|Yes| D{配列か?}
    D -->|Yes| E{Byte配列?}
    D -->|No| F[WriteIntrinsic]
    E -->|Yes| G[WriteBytes]
    E -->|No| H{Integer配列?}
    H -->|Yes| I[WriteIntegers]
    H -->|No| J[ArgumentException]
    F --> K{型判定}
    K -->|Boolean| L[WriteBoolean]
    K -->|Byte| M[WriteByte]
    K -->|Integer| N[WriteInt16]
    K -->|Long| O[WriteInt32]
    K -->|String| P[WriteString]
    K -->|その他| Q[対応する書き込み処理]
    L --> R[ストリームに書き込み]
    M --> R
    N --> R
    O --> R
    P --> S[長さプレフィックス書き込み]
    S --> T[エンコードバイト書き込み]
    Q --> R
    G --> R
    I --> R
    T --> R
    R --> U[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ストリーム書き込み可能チェック | 出力ストリームはCanWriteがTrueである必要がある | コンストラクタ呼び出し時 |
| BR-002 | 7ビット可変長エンコード | 文字列長は7ビット単位で書き込み、最上位ビットで継続を示す | 文字列書き込み時 |
| BR-003 | Decimalの.NET互換レイアウト | VBのDecimalレイアウトを.NET形式に変換して書き込む | Decimal書き込み時 |

### 計算ロジック

**7ビット可変長整数エンコード**:
```
Do While value > &H80
    WriteValue CByte((value And &H7F) Or &H80)
    value = (value And &HFFFFFF80) \ &H80
Loop
WriteValue CByte(value)
```

**Decimalレイアウト変換**:
- VB: bytes 0-1=Variant info, 2=precision, 3=sign, 4-7=high, 8-11=low, 12-15=mid
- .NET: bytes 0-3=low, 4-7=mid, 8-11=high, 12-13=unused, 14=precision, 15=sign

## データベース操作仕様

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ObjectDisposed_FileNotOpen | ObjectDisposedException | ストリームが閉じている状態でメソッド呼び出し | ストリームを再度オープンする |
| ArgumentNull_Stream | ArgumentNullException | OutputストリームがNothing | 有効なストリームを指定する |
| Argument_StreamNotWritable | ArgumentException | ストリームが書き込み不可 | 書き込み可能なストリームを指定する |
| Argument_UnsupportedArray | ArgumentException | サポートされない配列型 | Byte配列またはInteger配列を使用する |
| Argument_NeedIntrinsicType | ArgumentException | サポートされないデータ型 | サポートされているプリミティブ型を使用する |

### リトライ仕様

リトライ処理は実装されていない。エラー発生時は呼び出し元で対処する必要がある。

## トランザクション仕様

本機能はトランザクション管理を行わない。書き込みは即座にストリームに反映される（バッファリングはストリーム側で管理）。

## パフォーマンス要件

- 256バイト以下の文字列は内部バッファを再利用して効率的に処理
- 大きな文字列は一時的なバッファを作成して処理

## セキュリティ考慮事項

- ストリームの書き込み権限は呼び出し元で確保する必要がある
- 機密データを書き込む場合は、暗号化ストリーム（CryptoStream等）との組み合わせを推奨

## 備考

- .NET FrameworkのBinaryWriterクラスと互換性のある形式でデータを書き込む
- 文字エンコーディングはコンストラクタで指定可能（デフォルトはUTF-8）

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

プライベートメンバ変数を理解することで、BinaryWriterの内部状態が把握できる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | BinaryWriter.cls | `Source/CorLib/System.IO/BinaryWriter.cls` | 50-58行目のプライベート変数宣言を確認 |

**読解のコツ**: mOutStream（出力先）、mEncoding（文字エンコーディング）、mLargeBuffer（再利用バッファ）が主要な状態変数。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | BinaryWriter.cls | `Source/CorLib/System.IO/BinaryWriter.cls` | 236-253行目のInit関数でコンストラクタ処理を確認 |

**主要処理フロー**:
1. **237-240行目**: 入力バリデーション（NothingチェックとCanWriteチェック）
2. **242-248行目**: ストリームとエンコーディングの設定
3. **251-252行目**: バッファ初期化とMaxChars計算

#### Step 3: 書き込み処理の核心を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | BinaryWriter.cls | `Source/CorLib/System.IO/BinaryWriter.cls` | 159-168行目のWriteValue関数 |
| 3-2 | BinaryWriter.cls | `Source/CorLib/System.IO/BinaryWriter.cls` | 278-307行目のWriteIntrinsic関数 |
| 3-3 | BinaryWriter.cls | `Source/CorLib/System.IO/BinaryWriter.cls` | 358-376行目のWriteString関数 |

**主要処理フロー**:
- **162-167行目**: 配列と非配列の分岐処理
- **279-306行目**: VarType判定による型別書き込み分岐
- **359行目**: 文字列長の7ビット可変長エンコード呼び出し
- **265-276行目**: 7ビット可変長整数エンコードの実装

### プログラム呼び出し階層図

```
BinaryWriter
    │
    ├─ Init (コンストラクタ)
    │      └─ Encoding設定
    │
    ├─ WriteValue
    │      ├─ VerifyIsOpen
    │      ├─ WriteArray (配列の場合)
    │      │      ├─ WriteBytes
    │      │      └─ WriteIntegers
    │      └─ WriteIntrinsic (非配列の場合)
    │             ├─ WriteBoolean
    │             ├─ WriteByte
    │             ├─ WriteInt16
    │             ├─ WriteInt32
    │             ├─ WriteSingle
    │             ├─ WriteDouble
    │             ├─ WriteDate
    │             ├─ WriteCurrency
    │             ├─ WriteDecimal
    │             ├─ WriteString
    │             │      └─ WriteStringLength (7bit encoding)
    │             └─ WriteInt64
    │
    ├─ WriteChar
    │      └─ Encoding.GetBytesEx
    │
    ├─ Flush
    │      └─ Stream.Flush
    │
    └─ CloseWriter
           └─ Stream.CloseStream
```

### データフロー図

```
[入力]                    [処理]                         [出力]

Variant値 ─────────▶ WriteValue
                          │
                          ▼
                     型判定・変換
                          │
                          ▼
                     バイト配列化
                          │
                          ▼
                     Stream.WriteBlock ─────▶ ストリーム
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| BinaryWriter.cls | `Source/CorLib/System.IO/BinaryWriter.cls` | ソース | BinaryWriterクラス本体 |
| BinaryWriterTests.cls | `Source/Tests/System.IO/BinaryWriterTests.cls` | テスト | 単体テスト |
| Stream.cls | `Source/CorLib/System.IO/Stream.cls` | ソース | 出力先ストリームの基底クラス |
| Encoding.cls | `Source/CorLib/System.Text/Encoding.cls` | ソース | 文字エンコーディング |
| BitConverter.cls | `Source/CorLib/System/BitConverter.cls` | ソース | Decimal変換で使用 |
