# 機能設計書: StreamWriter

## 1. 機能概要

### 1.1 機能名
StreamWriter（ストリームライター）

### 1.2 機能ID
No.29

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

### 1.4 概要説明
StreamWriterは、特定のエンコーディングでバイトストリームに文字を書き込むクラスである。.NET FrameworkのStreamWriterクラスをVB6で実装したもので、テキストデータを効率的にストリームへ書き込む機能を提供する。

### 1.5 主な用途
- テキストファイルの作成・追記
- ネットワークストリームへのテキスト送信
- エンコーディングを考慮したテキスト出力
- 書式付き文字列の出力
- コンソール出力のバッファリング

---

## 2. 機能詳細

### 2.1 提供機能一覧

| No | 機能名 | 説明 |
|----|--------|------|
| 1 | WriteValue | 値を文字列として書き込み |
| 2 | WriteChars | 文字配列を書き込み |
| 3 | WriteLine | 行を書き込み（改行付き） |
| 4 | WriteLineChars | 文字配列を行として書き込み |
| 5 | Flush | バッファをストリームにフラッシュ |
| 6 | CloseWriter | ライターを閉じる |
| 7 | AutoFlush | 自動フラッシュの設定 |
| 8 | NewLine | 改行文字列の設定 |

### 2.2 処理フロー

#### 2.2.1 文字列書き込みフロー（WriteCore）
```
1. 文字列の長さを取得
   ↓
2. バッファに収まるか確認
   ├── 収まらない場合: InternalFlush実行
   └── 収まる場合: 次のステップへ
   ↓
3. 文字をバッファにコピー（CopyMemory）
   ↓
4. mPosition更新
   ↓
5. 残り文字があれば2に戻る
   ↓
6. AutoFlushがTrueの場合、InternalFlush実行
```

#### 2.2.2 フラッシュフロー（InternalFlush）
```
1. WritePreamble（BOM出力、初回のみ）
   ↓
2. mPosition > 0 の場合
   ├── エンコーダでバイト変換（GetBytes）
   └── ストリームにバイト書き込み（WriteBlock）
   ↓
3. mPositionをリセット
   ↓
4. FlushStreamがTrueの場合、ストリームをフラッシュ
```

### 2.3 データ構造

#### 2.3.1 クラスメンバ変数
```vb
Private mStream         As Stream       ' 基底ストリーム
Private mAutoFlush      As Boolean      ' 自動フラッシュフラグ
Private mEncoding       As Encoding     ' 現在のエンコーディング
Private mEncoder        As Encoder      ' エンコーダ
Private mNewLine        As String       ' 改行文字列
Private mCharBuffer()   As Integer      ' 文字バッファ
Private mByteBuffer()   As Byte         ' バイトバッファ
Private mBufferSize     As Long         ' バッファサイズ
Private mPosition       As Long         ' バッファ内位置
Private mIsOpen         As Boolean      ' オープン状態
Private mPreambleWritten As Boolean     ' BOM出力済みフラグ
Private mLeaveOpen      As Boolean      ' ストリーム維持フラグ
```

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

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

| インターフェース | 説明 |
|------------------|------|
| IObject | 基本オブジェクト機能（Equals, GetHashCode, ToString） |
| TextWriter | テキスト書き込み機能 |

---

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

### 3.1 パブリックAPI

#### 3.1.1 WriteValue メソッド
```vb
Public Sub WriteValue(ByRef Value As Variant, ParamArray Args() As Variant)
```
**パラメータ**:
- Value: 書き込む値
- Args: 書式引数（オプション）

**備考**: Argsがある場合はCorString.FormatArrayで書式化

#### 3.1.2 WriteChars メソッド
```vb
Public Sub WriteChars(ByRef Buffer() As Integer, Optional ByRef Index As Variant, Optional ByRef Count As Variant)
```
**パラメータ**:
- Buffer: 文字配列
- Index: 開始インデックス（オプション）
- Count: 文字数（オプション）

#### 3.1.3 WriteLine メソッド
```vb
Public Sub WriteLine(ParamArray Value() As Variant)
```
**パラメータ**:
- Value: 書き込む値と書式引数

**備考**: 値の後に改行文字列を追加

#### 3.1.4 WriteLineChars メソッド
```vb
Public Sub WriteLineChars(ByRef Buffer() As Integer, Optional ByRef Index As Variant, Optional ByRef Count As Variant)
```
**パラメータ**:
- Buffer: 文字配列
- Index: 開始インデックス（オプション）
- Count: 文字数（オプション）

**備考**: 文字配列の後に改行文字列を追加

#### 3.1.5 Flush メソッド
```vb
Public Sub Flush()
```
**備考**: バッファの内容をストリームにフラッシュ

#### 3.1.6 CloseWriter メソッド
```vb
Public Sub CloseWriter()
```
**備考**: LeaveOpen=Trueの場合、基底ストリームは閉じない

#### 3.1.7 AutoFlush プロパティ
```vb
Public Property Get AutoFlush() As Boolean
Public Property Let AutoFlush(ByVal Value As Boolean)
```
**備考**: Trueに設定すると、毎回の書き込み後に自動フラッシュ

#### 3.1.8 NewLine プロパティ
```vb
Public Property Get NewLine() As String
Public Property Let NewLine(ByVal Value As String)
```
**備考**: vbNullStringを設定するとvbCrLfにリセット

---

## 4. 内部処理詳細

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

**処理概要**（350-388行目）:
1. BufferSizeの検証
2. ソースタイプ判定
   - vbObject: Streamオブジェクトを設定
   - vbString: FileStreamを作成（Appendモード対応）
3. ストリーム位置が0より大きい場合、BOM出力済みとマーク
4. エンコーディング設定（デフォルトはUTF-8 BOMなし）
5. エンコーダ取得、改行文字列設定
6. バッファ初期化

### 4.2 WriteCore サブルーチン
文字列をバッファに書き込む。

**処理概要**（429-461行目）:
1. 文字列の長さとポインタを取得
2. バッファオーバーフロー時はInternalFlush実行
3. 書き込み可能な文字数を計算
4. CopyMemoryでバッファにコピー
5. 残り文字がある場合はループ

### 4.3 InternalFlush サブルーチン
バッファをストリームに書き込む。

**処理概要**（483-497行目）:
1. WritePreambleでBOM出力（初回のみ）
2. エンコーダでバイト変換
3. ストリームにバイト書き込み
4. mPositionをリセット
5. ストリームのフラッシュ（オプション）

### 4.4 WritePreamble サブルーチン
BOM（Byte Order Mark）を出力する。

**処理概要**（469-481行目）:
1. mPreambleWrittenがFalseの場合のみ実行
2. エンコーディングからBOM取得
3. BOMがあればストリームに書き込み
4. mPreambleWrittenをTrueに設定

---

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

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

| クラス名 | 用途 |
|----------|------|
| Stream | 基底ストリーム（FileStream, MemoryStream等） |
| Encoding | 文字エンコーディング |
| Encoder | 状態を持つエンコーダ |
| FileStream | ファイルパス指定時に自動作成 |
| CultureInfo | 書式プロバイダ |
| CorString | 書式化ユーティリティ |

---

## 6. エラー処理

### 6.1 例外一覧

| 例外 | 発生条件 |
|------|----------|
| ArgumentNullException | SourceがNothing、Bufferが未初期化 |
| ArgumentOutOfRangeException | BufferSizeが負数 |
| ArgumentException | Sourceが無効な型、Streamでない |
| ObjectDisposedException | 閉じられたライターへの操作 |
| FormatException | 書式文字列が無効 |

---

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

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

### 7.2 推奨事項
- 大量書き込み時はAutoFlushをFalseに設定
- 書き込み完了後は必ずCloseWriterまたはFlushを呼び出す
- 頻繁な小さい書き込みは避け、まとめて書き込む
- BOMが不要な場合はUTF-8 BOMなしエンコーディングを使用

---

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

### 8.1 推奨読解順序

1. **データ構造の理解**
   - `StreamWriter.cls` 56-67行目: メンバ変数定義
   - 54行目: MIN_BUFFERSIZE定数

2. **初期化処理**
   - `Init` (350-388行目): 初期化
   - `Class_Terminate` (390-392行目): 終了処理

3. **基本操作**
   - `WriteValue` (196-210行目): 値書き込み
   - `WriteChars` (230-244行目): 文字配列書き込み
   - `WriteLine` (272-286行目): 行書き込み
   - `Flush` (166-169行目): フラッシュ
   - `CloseWriter` (144-161行目): クローズ

4. **内部アルゴリズム**
   - `WriteCore` (429-461行目): コア書き込み処理
   - `InternalFlush` (483-497行目): 内部フラッシュ
   - `WritePreamble` (469-481行目): BOM出力
   - `VerifyIsOpen` (463-467行目): オープン確認

5. **書式処理**
   - `WriteFormatLine` (398-417行目): 書式付き行出力
   - `WriteFormatToStream` (419-423行目): 書式付き出力
   - `WriteValueToStream` (425-427行目): 値出力

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

```
StreamWriter.Init
  ├── [vbObject] Stream設定
  │     └── mLeaveOpen設定
  ├── [vbString] Cor.NewFileStream
  │     └── FileMode判定（Append/Create）
  ├── Stream.CanSeek/Position確認
  ├── Encoding.GetEncoder
  └── ReDim mCharBuffer, mByteBuffer

StreamWriter.WriteValue
  ├── VerifyIsOpen
  ├── [引数あり] WriteFormatToStream
  │     └── CorString.FormatArray
  └── [引数なし] WriteValueToStream
        └── Object.ToString
  └── WriteCore
        ├── CopyMemory
        └── InternalFlush（必要時）

StreamWriter.Flush
  ├── VerifyIsOpen
  └── InternalFlush
        ├── WritePreamble
        │     └── mEncoding.GetPreamble
        ├── mEncoder.GetBytes
        └── mStream.WriteBlock
```

### 8.3 データフロー図

```
[Value/文字列]
      │
      ↓
[WriteValue/WriteChars]
      │
      ↓
[WriteCore] ──→ [mCharBuffer]
                     │
                     ↓
              [InternalFlush]
                     │
                     ├── [WritePreamble] ──→ [BOM出力]
                     │
                     ↓
              [Encoder.GetBytes]
                     │
                     ↓
              [mByteBuffer]
                     │
                     ↓
              [Stream.WriteBlock]
                     │
                     ↓
                 [Stream]
```

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

| パス | 種別 | 役割 |
|------|------|------|
| Source/CorLib/System.IO/StreamWriter.cls | クラス | メインクラス |
| Source/CorLib/System.IO/TextWriter.cls | インターフェース | テキスト書き込み契約 |
| Source/CorLib/System.IO/Stream.cls | インターフェース | ストリーム基底 |
| Source/CorLib/System.Text/Encoding.cls | クラス | エンコーディング |
| Source/CorLib/System.Text/Encoder.cls | クラス | エンコーダ |

### 8.5 読解のコツ
- mCharBufferはInteger配列（VB6のIntegerは16ビット = UTF-16相当）
- デフォルトエンコーディングはStream.UTF8NoBOMAndThrows（BOMなしUTF-8）
- HaveWrittenPreambleはConsole用に公開されている（BOM出力抑制）
- WriteFormatLineではHelper.MoveVariantで最初の引数を抽出
- mNewLineのデフォルトはEnvironment.NewLine
- LeaveOpenがTrueの場合、CloseWriter時に基底ストリームを閉じない

---

## 9. 変更履歴

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

---

## 10. 備考

- .NET FrameworkのSystem.IO.StreamWriterと互換性のあるAPI設計
- デフォルトエンコーディングはBOMなしUTF-8
- TextWriterインターフェースを実装
- 文字列またはStreamオブジェクトから初期化可能
- Appendモード対応（ファイルパス指定時）
- ParamArrayを使用した可変長引数での書式化をサポート
