# 機能設計書: StreamReader

## 1. 機能概要

### 1.1 機能名
StreamReader（ストリームリーダー）

### 1.2 機能ID
No.28

### 1.3 機能分類
System.IO - 入出力

### 1.4 概要説明
StreamReaderは、特定のエンコーディングでバイト配列から文字を読み取るクラスである。.NET FrameworkのStreamReaderクラスをVB6で実装したもので、ストリームからテキストデータを効率的に読み取り、文字列として返す機能を提供する。

### 1.5 主な用途
- テキストファイルの読み取り
- ネットワークストリームからのテキスト受信
- エンコーディングを考慮したテキスト読み取り
- 行単位でのテキスト処理
- BOM（Byte Order Mark）からのエンコーディング自動検出

---

## 2. 機能詳細

### 2.1 提供機能一覧

| No | 機能名 | 説明 |
|----|--------|------|
| 1 | Read | 1文字読み取り |
| 2 | Peek | 次の文字を消費せずに取得 |
| 3 | ReadBlock | 複数文字読み取り |
| 4 | ReadLine | 1行読み取り |
| 5 | ReadToEnd | 残りすべてを読み取り |
| 6 | CloseReader | リーダーを閉じる |
| 7 | DiscardBufferedData | バッファをクリア |
| 8 | EndOfStream | ストリーム終端判定 |

### 2.2 処理フロー

#### 2.2.1 文字読み取りフロー（Read）
```
1. オープン確認（VerifyIsOpen）
   ↓
2. HaveChars（文字バッファ確認）
   ├── バッファに文字がある場合: True
   └── バッファが空の場合: ReadBuffer実行
         ├── ストリームからバイト読み取り
         ├── BOM判定（初回のみ）
         └── デコーダで文字変換
   ↓
3. 文字があれば返却、なければ-1
```

#### 2.2.2 行読み取りフロー（ReadLine）
```
1. オープン確認（VerifyIsOpen）
   ↓
2. HaveChars確認
   ↓
3. 改行文字（CR/LF）を探索
   ├── バッファ内で見つかった場合
   │     文字列を作成して返却
   └── バッファ終端まで見つからない場合
         StringBuilderに追加してバッファ再充填
   ↓
4. CR-LF対応（CRの次がLFなら両方スキップ）
   ↓
5. 文字列を返却
```

### 2.3 データ構造

#### 2.3.1 クラスメンバ変数
```vb
Private mStream             As Stream       ' 基底ストリーム
Private mEncoding           As Encoding     ' 現在のエンコーディング
Private mDecoder            As Decoder      ' デコーダ
Private mByteBuffer()       As Byte         ' バイトバッファ
Private mByteIndex          As Long         ' バイトバッファ位置
Private mByteLength         As Long         ' バイトバッファ長
Private mCharBuffer()       As Integer      ' 文字バッファ
Private mCharIndex          As Long         ' 文字バッファ位置
Private mCharLength         As Long         ' 文字バッファ長
Private mBufferSize         As Long         ' バッファサイズ
Private mDetermineEncoding  As Boolean      ' BOM判定フラグ
Private mIsOpen             As Boolean      ' オープン状態
Private mLineBuilder        As StringBuilder ' 行構築用
Private mLeaveOpen          As Boolean      ' ストリーム維持フラグ
```

#### 2.3.2 定数定義
```vb
Private Const MinimumBufferSize As Long = 128    ' 最小バッファサイズ
```

### 2.4 エンコーディング自動検出

BOM（Byte Order Mark）からエンコーディングを自動検出：

| BOM | エンコーディング |
|-----|------------------|
| FF FE | Unicode (Little Endian) |
| FE FF | Unicode (Big Endian) |
| EF BB BF | UTF-8 |
| FF FE 00 00 | UTF-32 (Little Endian) |
| 00 00 FE FF | UTF-32 (Big Endian) |

### 2.5 実装インターフェース

| インターフェース | 説明 |
|------------------|------|
| IObject | 基本オブジェクト機能（Equals, GetHashCode, ToString） |
| TextReader | テキスト読み取り機能 |

---

## 3. インターフェース仕様

### 3.1 パブリックAPI

#### 3.1.1 Read メソッド
```vb
Public Function Read() As Long
```
**戻り値**: 読み取った文字（0-65535）、ストリーム終端の場合は-1

#### 3.1.2 Peek メソッド
```vb
Public Function Peek() As Long
```
**戻り値**: 次の文字（消費しない）、ストリーム終端の場合は-1

#### 3.1.3 ReadBlock メソッド
```vb
Public Function ReadBlock(ByRef Buffer() As Integer, ByVal Index As Long, ByVal Count As Long) As Long
```
**パラメータ**:
- Buffer: 読み取り先の文字配列
- Index: 配列内の開始インデックス
- Count: 読み取る文字数

**戻り値**: 実際に読み取った文字数

#### 3.1.4 ReadLine メソッド
```vb
Public Function ReadLine() As String
```
**戻り値**: 次の行（改行文字を除く）、ストリーム終端の場合はvbNullString

**備考**: CR, LF, CR+LF を改行として認識

#### 3.1.5 ReadToEnd メソッド
```vb
Public Function ReadToEnd() As String
```
**戻り値**: 現在位置から終端までのすべての文字列

#### 3.1.6 CloseReader メソッド
```vb
Public Sub CloseReader()
```
**備考**: LeaveOpen=Trueで作成された場合、基底ストリームは閉じない

#### 3.1.7 DiscardBufferedData メソッド
```vb
Public Sub DiscardBufferedData()
```
**備考**: 基底ストリームの位置が変更された場合に使用

#### 3.1.8 EndOfStream プロパティ
```vb
Public Property Get EndOfStream() As Boolean
```
**戻り値**: ストリーム終端に達した場合True

---

## 4. 内部処理詳細

### 4.1 Init サブルーチン
ストリームまたはファイルパスからリーダーを初期化する。

**処理概要**（358-371行目）:
1. BufferSizeの検証
2. CreateStreamでストリーム作成（文字列ならFileStreamを作成）
3. エンコーディング設定（デフォルトはUTF-8）
4. デコーダ取得
5. バッファ初期化

### 4.2 ReadBuffer 関数
ストリームからバッファを充填する。

**処理概要**（412-442行目）:
1. ストリームからバイト読み取り
2. BOM判定（初回のみ）
3. 文字バッファ初期化（必要に応じて）
4. デコーダで文字変換
5. インデックスリセット

### 4.3 DetermineEncoding サブルーチン
BOMからエンコーディングを判定する。

**処理概要**（444-496行目）:
1. 最初の2バイトを読み取り
2. BOMパターンに応じてエンコーディングを設定
3. バイトインデックスを調整（BOMをスキップ）

### 4.4 HaveChars 関数
文字バッファに文字があるか確認する。

**処理概要**（399-410行目）:
1. mCharIndex = mCharLengthなら ReadBuffer 実行
2. 読み取れた文字数が0より大きければTrue

---

## 5. 関連コンポーネント

### 5.1 依存クラス/モジュール

| クラス名 | 用途 |
|----------|------|
| Stream | 基底ストリーム（FileStream, MemoryStream等） |
| Encoding | 文字エンコーディング |
| Decoder | 状態を持つデコーダ（マルチバイト文字対応） |
| StringBuilder | 行構築用 |
| FileStream | ファイルパス指定時に自動作成 |

---

## 6. エラー処理

### 6.1 例外一覧

| 例外 | 発生条件 |
|------|----------|
| ArgumentNullException | StreamがNothing |
| ArgumentOutOfRangeException | BufferSizeが0以下 |
| ArgumentException | Sourceが無効な型、Streamでない |
| ObjectDisposedException | 閉じられたリーダーへの操作 |

---

## 7. パフォーマンス考慮

### 7.1 バッファリング
- 最小バッファサイズ: 128バイト
- デコーダは状態を維持してマルチバイト文字に対応

### 7.2 推奨事項
- 大きなファイルを読む場合はバッファサイズを増やす
- 頻繁なReadLineよりReadToEnd + Splitが効率的な場合あり
- DiscardBufferedDataはストリーム位置変更後に使用

---

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

### 8.1 推奨読解順序

1. **データ構造の理解**
   - `StreamReader.cls` 58-71行目: メンバ変数定義
   - 56行目: MinimumBufferSize定数

2. **初期化処理**
   - `Init` (358-371行目): 初期化
   - `CreateStream` (381-397行目): ストリーム作成

3. **基本操作**
   - `Peek` (140-148行目): 文字プレビュー
   - `Read` (156-162行目): 1文字読み取り
   - `ReadBlock` (172-198行目): 複数文字読み取り
   - `ReadLine` (207-298行目): 行読み取り
   - `ReadToEnd` (305-326行目): 全文読み取り

4. **内部アルゴリズム**
   - `HaveChars` (399-410行目): 文字確認
   - `ReadBuffer` (412-442行目): バッファ充填
   - `DetermineEncoding` (444-496行目): BOM判定

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

```
StreamReader.Init
  ├── CreateStream
  │     ├── [vbObject] Stream設定
  │     └── [vbString] Cor.NewFileStream
  ├── Encoding.GetDecoder
  └── ReDim mByteBuffer

StreamReader.ReadLine
  ├── VerifyIsOpen
  ├── HaveChars
  │     └── ReadBuffer
  │           ├── Stream.ReadBlock
  │           ├── DetermineEncoding
  │           │     └── SetEncodingFromBOM
  │           └── Decoder.GetChars
  ├── mLineBuilder.Append
  └── Cor.NewString / mLineBuilder.ToString
```

### 8.3 データフロー図

```
[Stream] ──→ [ReadBlock] ──→ [mByteBuffer]
                                   │
                                   ↓
                          [DetermineEncoding]
                                   │
                                   ↓
                          [Decoder.GetChars]
                                   │
                                   ↓
                          [mCharBuffer]
                                   │
               ┌───────────────────┼───────────────────┐
               ↓                   ↓                   ↓
           [Read]             [ReadLine]        [ReadToEnd]
               │                   │                   │
               ↓                   ↓                   ↓
          [1文字]            [文字列行]          [全文字列]
```

### 8.4 関連ファイル一覧

| パス | 種別 | 役割 |
|------|------|------|
| Source/CorLib/System.IO/StreamReader.cls | クラス | メインクラス |
| Source/CorLib/System.IO/TextReader.cls | インターフェース | テキスト読み取り契約 |
| Source/CorLib/System.IO/Stream.cls | インターフェース | ストリーム基底 |
| Source/CorLib/System.Text/Encoding.cls | クラス | エンコーディング |
| Source/CorLib/System.Text/Decoder.cls | クラス | デコーダ |
| Source/CorLib/System.Text/StringBuilder.cls | クラス | 文字列構築 |

### 8.5 読解のコツ
- mCharBufferはInteger配列（VB6のIntegerは16ビット = UTF-16相当）
- vbReturnChar, vbLineFeedChar は改行文字の定数
- Decoder.GetCharsは状態を保持するためマルチバイト文字の途中で切れても対応可能
- Cor.NewStringは文字配列から文字列を作成するヘルパー
- mLeaveOpenがTrueの場合、CloseReader時に基底ストリームを閉じない

---

## 9. 変更履歴

| 日付 | バージョン | 変更内容 |
|------|------------|----------|
| 2012 | 1.0 | 初期実装（Kelly Ethridge） |

---

## 10. 備考

- .NET FrameworkのSystem.IO.StreamReaderと互換性のあるAPI設計
- デフォルトエンコーディングはUTF-8
- BOMによるエンコーディング自動検出をサポート
- TextReaderインターフェースを実装
- 文字列またはStreamオブジェクトから初期化可能
