# 機能設計書 41-IniResourceWriter

## 概要

本ドキュメントは、VBCorLibライブラリにおけるINIファイル形式リソース書き込み機能「IniResourceWriter」クラスの機能設計について記述する。

### 本機能の処理概要

IniResourceWriterクラスは、キーと値のペアをINIファイルの特定セクションに一括で書き込むリソースライターである。IResourceWriterインターフェースを実装し、.NET Frameworkのリソース書き込みパターンに準拠している。

**業務上の目的・背景**：設定ファイルやリソースデータをINI形式で保存する必要がある場合、個別にキー/値ペアを書き込むのではなく、一括でセクション全体を生成することで効率的なファイル操作を実現する。既存のセクション内容を完全に置き換える仕様により、設定の整合性を保証する。

**機能の利用シーン**：
- アプリケーション設定のINIファイルへの保存
- リソースデータのINI形式でのエクスポート
- 設定セクション全体の一括更新
- 多言語リソースのINI形式での保存

**主要な処理内容**：
1. INIファイル名とセクション名の指定によるライター初期化
2. AddResourceメソッドによるキー/値ペアの蓄積
3. Generateメソッドによる一括書き込み実行
4. CloseWriterメソッドによるリソース解放（暗黙的なGenerate呼び出しを含む）

**関連システム・外部連携**：Windows API（WritePrivateProfileSectionW、WritePrivateProfileStringW）を使用してINIファイルへの書き込みを行う。

**権限による制御**：対象ファイルへの書き込み権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は画面からの直接操作を持たない |

## 機能種別

ファイル出力処理 / リソース管理機能

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| FileName | String | Yes | INIファイルのパス | 空文字列不可 |
| Section | String | Yes | INIファイル内のセクション名 | 空文字列不可 |
| Key | String | Yes | AddResourceメソッドのキー | 空文字列不可 |
| Value | Variant | Yes | AddResourceメソッドの値 | IObject実装オブジェクトまたは基本型 |

### 入力データソース

プログラムからの直接呼び出し（パラメータ指定）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| INIファイル | ファイル | 指定セクションにキー=値形式でデータが書き込まれる |

### 出力先

指定されたINIファイルの指定セクション

### 出力フォーマット

```ini
[セクション名]
キー1=値1
キー2=値2
...
```

## 処理フロー

### 処理シーケンス

```
1. インスタンス生成（Initメソッド経由）
   └─ FileName、Sectionのバリデーション
   └─ Hashtableの初期化（キー/値ペア格納用）
2. AddResource呼び出し（複数回）
   └─ キーの空文字列チェック
   └─ Generate済みチェック
   └─ Hashtableへのキー/値追加
3. Generate呼び出し
   └─ Generate済みチェック
   └─ StringBuilderによる出力文字列構築
   └─ WritePrivateProfileSectionW APIの呼び出し
   └─ WritePrivateProfileStringW APIでキャッシュフラッシュ
   └─ Hashtableの解放（Nothing設定）
4. CloseWriter呼び出し
   └─ 未Generate時はGenerateを実行
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[Init: FileName, Section設定]
    B --> C{FileName空?}
    C -->|Yes| D[ArgumentException]
    C -->|No| E{Section空?}
    E -->|Yes| F[ArgumentException]
    E -->|No| G[Hashtable初期化]
    G --> H[AddResource呼び出し]
    H --> I{Key空?}
    I -->|Yes| J[ArgumentException]
    I -->|No| K{Generate済み?}
    K -->|Yes| L[InvalidOperationException]
    K -->|No| M[Hashtableに追加]
    M --> N{追加継続?}
    N -->|Yes| H
    N -->|No| O[Generate呼び出し]
    O --> P{Generate済み?}
    P -->|Yes| L
    P -->|No| Q[StringBuilder構築]
    Q --> R[WritePrivateProfileSectionW]
    R --> S{API成功?}
    S -->|No| T[IOError]
    S -->|Yes| U[キャッシュフラッシュ]
    U --> V[Hashtable解放]
    V --> W[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ファイル名必須 | FileNameは空文字列であってはならない | Init時 |
| BR-002 | セクション名必須 | Sectionは空文字列であってはならない | Init時 |
| BR-003 | キー名必須 | AddResourceのKeyは空文字列であってはならない | AddResource時 |
| BR-004 | 単一Generate | Generateは1回のみ実行可能、以降のAdd/Generateはエラー | Generate呼び出し後 |
| BR-005 | セクション置換 | 既存セクションの内容は完全に削除され、新しい内容で置き換えられる | Generate時 |
| BR-006 | 暗黙Generate | CloseWriter呼び出し時に未Generateの場合、自動的にGenerateが実行される | CloseWriter時 |

### 計算ロジック

```
出力文字列 = キー1 + "=" + 値1 + NullChar + キー2 + "=" + 値2 + NullChar + ... + NullChar
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentException | FileNameが空文字列 | 有効なファイルパスを指定 |
| - | ArgumentException | Sectionが空文字列 | 有効なセクション名を指定 |
| - | ArgumentException | AddResourceのKeyが空文字列 | 有効なキー名を指定 |
| - | InvalidOperationException | Generate後にAddResourceまたはGenerate呼び出し | 新しいインスタンスを作成 |
| - | IOError | WritePrivateProfileSectionW失敗 | ファイルの書き込み権限確認 |

### リトライ仕様

ファイルI/O処理のため、リトライは呼び出し元で実装する必要がある。

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

本機能はトランザクション処理を行わない。セクション書き込みはアトミックではなく、部分的な書き込みが発生する可能性がある。

## パフォーマンス要件

- 数十件のキー/値ペア書き込み: 数ミリ秒以内
- INIファイルの最大セクションサイズ: Windowsの制限に依存（通常32KB）

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

- INIファイルはプレーンテキストで保存されるため、機密情報の格納には不適
- ファイルパスにはユーザー入力を直接使用しない（パストラバーサル攻撃の防止）
- 書き込み対象ファイルの権限を適切に設定すること

## 備考

- INIファイル形式はWindowsの古い設定保存形式であり、新規開発では他の形式（XML、JSON等）を推奨
- 既存のセクション内容は完全に削除されるため、マージが必要な場合は事前に読み込みが必要
- WritePrivateProfileSectionW APIはWindows固有のため、他のプラットフォームでは動作しない

---

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

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

### 推奨読解順序

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

IniResourceWriterクラスは内部でHashtableを使用してキー/値ペアを管理する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IniResourceWriter.cls | `Source/CorLib/System.IO/IniResourceWriter.cls` | クラスの全体構造、プライベート変数（mFileName、mSection、mValues）の定義 |

**読解のコツ**: 49-51行目でプライベートメンバ変数が定義されている。mValuesがHashtableである点が重要で、キーの一意性が保証される。

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

主要なエントリーポイントはAddResource、Generate、CloseWriterの3メソッドである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | IniResourceWriter.cls | `Source/CorLib/System.IO/IniResourceWriter.cls` | 公開プロパティ（FileName、Section）とメソッド（AddResource、Generate、CloseWriter） |

**主要処理フロー**:
1. **59-61行目**: FileNameプロパティ - INIファイル名を返す読み取り専用プロパティ
2. **68-70行目**: Sectionプロパティ - セクション名を返す読み取り専用プロパティ
3. **81-87行目**: AddResourceメソッド - キー/値ペアをHashtableに追加
4. **95-115行目**: Generateメソッド - INIファイルへの一括書き込み
5. **121-125行目**: CloseWriterメソッド - リソース解放と暗黙Generate

#### Step 3: コア処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | IniResourceWriter.cls | `Source/CorLib/System.IO/IniResourceWriter.cls` | Generateメソッドの詳細とWindows API呼び出し |

**主要処理フロー**:
- **96-100行目**: StringBuilderでキー=値形式の文字列を構築
- **101-106行目**: DictionaryEntryをループしてkey=value+NullChar形式で追加
- **108行目**: 終端NullCharの追加
- **110-111行目**: WritePrivateProfileSectionW APIの呼び出しとエラーチェック
- **113行目**: WritePrivateProfileStringW APIによるキャッシュフラッシュ
- **114行目**: mValues = NothingでGenerate完了をマーク

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

```
Cor.NewIniResourceWriter(FileName, Section)
    │
    └─ IniResourceWriter.Init(FileName, Section)
            │
            ├─ FileName/Sectionバリデーション
            └─ Set mValues = New Hashtable

AddResource(Key, Value)
    │
    ├─ Key空チェック
    ├─ VerifyNotGenerated()
    │       └─ mValues Is Nothing? → InvalidOperationException
    └─ mValues.Add(Key, Value)

Generate()
    │
    ├─ VerifyNotGenerated()
    ├─ StringBuilder.Append/AppendChar [ループ]
    ├─ WritePrivateProfileSectionW API
    │       └─ 失敗時: IOError.WinIOError
    ├─ WritePrivateProfileStringW API (フラッシュ)
    └─ Set mValues = Nothing

CloseWriter()
    │
    └─ mValues Is Nothing?
            └─ No: Generate()
```

### データフロー図

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

FileName,Section ────────▶ Init ──────────────────────▶ インスタンス初期化
                              │
                              ▼
                          Hashtable生成

Key,Value ─────────────────▶ AddResource ─────────────▶ Hashtable蓄積
                              │
                              ▼
                          mValues.Add

（なし） ──────────────────▶ Generate ─────────────────▶ INIファイル
                              │
                              ├─ StringBuilder構築
                              │     "Key=Value\0..."
                              ▼
                          WritePrivateProfileSectionW
                              │
                              ▼
                          キャッシュフラッシュ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IniResourceWriter.cls | `Source/CorLib/System.IO/IniResourceWriter.cls` | ソース | メインクラス定義（205行） |
| IniResourceWriterTests.cls | `Source/Tests/System.IO/IniResourceWriterTests.cls` | テスト | 単体テストケース |
| IResourceWriter.cls | `Source/CorLib/System.Resources/IResourceWriter.cls` | インターフェース | リソースライターインターフェース |
| Constructors.cls | `Source/CorLib/Constructors.cls` | ソース | NewIniResourceWriterファクトリメソッド |
| Hashtable.cls | `Source/CorLib/System.Collections/Hashtable.cls` | ソース | キー/値ペア格納用コレクション |
| StringBuilder.cls | `Source/CorLib/System.Text/StringBuilder.cls` | ソース | 出力文字列構築用 |
| Error.cls | `Source/CorLib/System/Error.cls` | ソース | 例外スロー処理 |
| IOError.cls | `Source/CorLib/System.IO/IOError.cls` | ソース | IO例外処理 |
