# 機能設計書: FileStream

## 1. 機能概要

### 1.1 機能名
FileStream（ファイルストリーム）

### 1.2 機能ID
No.26

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

### 1.4 概要説明
FileStreamは、ファイルをストリームとして表現するクラスである。.NET FrameworkのFileStreamクラスをVB6で実装したもので、ディスク上のファイルに対する読み書き、シーク操作、およびロック操作を提供する。バッファリングによりパフォーマンスを最適化し、同期/非同期操作の両方をサポートする。

### 1.5 主な用途
- ファイルの読み取り（バイナリ/テキスト）
- ファイルへの書き込み
- ファイル内の任意の位置へのシーク
- ファイルのロック/アンロック
- 既存のファイルハンドルをストリームとしてラップ

---

## 2. 機能詳細

### 2.1 提供機能一覧

| No | 機能名 | 説明 |
|----|--------|------|
| 1 | ReadByte | 1バイト読み取り |
| 2 | ReadBlock | 複数バイト読み取り |
| 3 | WriteByte | 1バイト書き込み |
| 4 | WriteBlock | 複数バイト書き込み |
| 5 | SeekPosition | ストリーム内の位置を移動 |
| 6 | Flush | バッファをファイルにフラッシュ |
| 7 | CloseStream | ストリームを閉じる |
| 8 | SetLength | ファイル長を設定 |
| 9 | LockStream | ファイルの一部をロック |
| 10 | UnlockStream | ファイルのロックを解除 |
| 11 | CopyTo | 別のストリームにコピー |
| 12 | BeginRead | 非同期読み取り開始 |
| 13 | EndRead | 非同期読み取り終了 |
| 14 | BeginWrite | 非同期書き込み開始 |
| 15 | EndWrite | 非同期書き込み終了 |

### 2.2 処理フロー

#### 2.2.1 読み取りフロー（ReadBlock）
```
1. 配列範囲検証（ValidateArrayRange）
   ↓
2. 読み取り可能性チェック（VerifyCanRead）
   ↓
3. ストリームオープン確認（VerifyIsOpen）
   ↓
4. バッファが空または読み取り位置が終端の場合
   ├── 書き込みデータがあればFlush
   └── FillBuffer（ファイルからバッファへ読み込み）
   ↓
5. バッファからデータをコピー
   ├── 要求量がバッファ残量以下: バッファからコピー
   └── 要求量がバッファ残量超過: バッファ + 直接ファイル読み取り
   ↓
6. 位置を更新して読み取りバイト数を返却
```

#### 2.2.2 書き込みフロー（WriteBlock）
```
1. 配列範囲検証（ValidateArrayRange）
   ↓
2. 書き込み可能性チェック（VerifyCanWrite）
   ↓
3. ストリームオープン確認（VerifyIsOpen）
   ↓
4. バッファ初期化（必要に応じて）
   ↓
5. 読み取りバッファにデータがあれば位置をシーク
   ↓
6. バッファに収まらない場合はFlush
   ↓
7. バッファサイズ超過の場合
   │   直接ファイルに書き込み（WriteFile API）
   ↓
   バッファサイズ以内の場合
   │   バッファにコピー
   ↓
8. 位置を更新
```

### 2.3 データ構造

#### 2.3.1 クラスメンバ変数
```vb
Private mName           As String           ' ファイル名
Private mHandle         As SafeFileHandle   ' ファイルハンドル
Private mCanRead        As Boolean          ' 読み取り可能フラグ
Private mCanWrite       As Boolean          ' 書き込み可能フラグ
Private mCanSeek        As Boolean          ' シーク可能フラグ
Private mMinPosition    As Currency         ' 最小位置（Appendモード用）
Private mFilePosition   As Currency         ' 現在のファイル位置
Private mWritePosition  As Long             ' 書き込みバッファ位置
Private mReadPosition   As Long             ' 読み取りバッファ位置
Private mBuffer()       As Byte             ' 内部バッファ
Private mBufferSize     As Long             ' バッファサイズ
Private mBufferOffset   As Currency         ' バッファのファイル内オフセット
Private mBytesBuffered  As Long             ' バッファ内の有効バイト数
Private mIsAsync        As Boolean          ' 非同期モードフラグ
Private mActiveAsyncResult As IAsyncResult  ' アクティブな非同期結果
```

#### 2.3.2 定数・列挙型
```vb
Private Const MinBufferSize As Long = 8     ' 最小バッファサイズ

' ファイルモード
Public Enum FileMode
    CreateNew = 1       ' 新規作成（存在すればエラー）
    Create = 2          ' 作成（存在すれば上書き）
    OpenExisting = 3    ' 既存を開く（存在しなければエラー）
    OpenOrCreate = 4    ' 開くか作成
    Truncate = 5        ' 切り詰めて開く
    Append = 6          ' 追記モード
End Enum

' ファイルアクセス
Public Enum FileAccess
    ReadAccess = 1
    WriteAccess = 2
    ReadWriteAccess = 3
End Enum

' ファイル共有
Public Enum FileShare
    None = 0
    ReadShare = 1
    WriteShare = 2
    ReadWriteShare = 3
End Enum
```

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

| インターフェース | 説明 |
|------------------|------|
| IObject | 基本オブジェクト機能（Equals, GetHashCode, ToString） |
| Stream | ストリーム抽象クラス機能 |

---

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

### 3.1 パブリックAPI

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

#### 3.1.2 ReadBlock メソッド
```vb
Public Function ReadBlock(ByRef Bytes() As Byte, ByVal Offset As Long, ByVal Count As Long) As Long
```
**パラメータ**:
- Bytes: 読み取りデータを格納する配列
- Offset: 配列内の開始インデックス
- Count: 読み取るバイト数

**戻り値**: 実際に読み取ったバイト数

#### 3.1.3 WriteByte メソッド
```vb
Public Sub WriteByte(ByVal Value As Byte)
```
**パラメータ**:
- Value: 書き込むバイト値

#### 3.1.4 WriteBlock メソッド
```vb
Public Sub WriteBlock(ByRef Bytes() As Byte, ByVal Offset As Long, ByVal Count As Long)
```
**パラメータ**:
- Bytes: 書き込みデータを含む配列
- Offset: 配列内の開始インデックス
- Count: 書き込むバイト数

#### 3.1.5 SeekPosition メソッド
```vb
Public Function SeekPosition(ByVal Offset As Currency, ByVal Origin As SeekOrigin) As Currency
```
**パラメータ**:
- Offset: 移動量（バイト）
- Origin: 基準位置（FromBeginning/FromCurrent/FromEnd）

**戻り値**: 新しいストリーム位置

#### 3.1.6 SetLength メソッド
```vb
Public Sub SetLength(ByVal Value As Currency)
```
**パラメータ**:
- Value: 新しいファイル長

#### 3.1.7 LockStream メソッド
```vb
Public Sub LockStream(ByVal Position As Currency, ByVal Length As Currency)
```
**パラメータ**:
- Position: ロック開始位置
- Length: ロックするバイト数

#### 3.1.8 UnlockStream メソッド
```vb
Public Sub UnlockStream(ByVal Position As Currency, ByVal Length As Currency)
```
**パラメータ**:
- Position: アンロック開始位置
- Length: アンロックするバイト数

---

## 4. 内部処理詳細

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

**処理概要**（839-882行目）:
1. パスのトリムと検証
2. パラメータ検証（BufferSize, Mode, Access, Share）
3. Appendモードの特別処理
4. SafeCreateFileでファイルハンドル取得
5. 機能フラグの設定（CanRead, CanWrite, CanSeek）
6. Appendモード時の位置設定

### 4.2 FillBuffer サブルーチン
ファイルからバッファにデータを読み込む。

**処理概要**（936-950行目）:
1. バッファオフセットを現在位置に設定
2. 読み取り/書き込み位置をリセット
3. バッファが未初期化なら初期化
4. ReadFile APIでファイルから読み込み

### 4.3 InternalSeek 関数
Win32 APIを使用してファイルポインタを移動する。

**処理概要**（952-970行目）:
1. オフセットをDLong構造に変換
2. SetFilePointer APIを呼び出し
3. エラーチェックと新位置の返却

### 4.4 Flush サブルーチン
書き込みバッファの内容をファイルに書き出す。

**処理概要**（739-753行目）:
1. 書き込み可能性とオープン確認
2. 書き込み位置が0より大きい場合
3. WriteFile APIでバッファ内容を書き込み
4. バッファ位置をリセット

---

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

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

| クラス名 | 用途 |
|----------|------|
| SafeFileHandle | ファイルハンドルの安全な管理 |
| StreamAsyncResult | 非同期操作結果 |
| IOError | I/Oエラー処理 |
| Stream | 基底インターフェース |
| Path | パス操作ユーティリティ |

### 5.2 使用するWin32 API

| API名 | 用途 |
|-------|------|
| CreateFile | ファイルを開く/作成 |
| ReadFile | ファイルから読み取り |
| WriteFile | ファイルへ書き込み |
| SetFilePointer | ファイルポインタを移動 |
| GetFileSize | ファイルサイズを取得 |
| SetEndOfFile | ファイル終端を設定 |
| LockFile | ファイルをロック |
| UnlockFile | ファイルのロックを解除 |
| GetFileType | ファイルタイプを取得 |

---

## 6. エラー処理

### 6.1 例外一覧

| 例外 | 発生条件 |
|------|----------|
| ArgumentException | 空のパス、無効なFileModeとAccessの組み合わせ |
| ArgumentOutOfRangeException | 無効なBufferSize、負のPosition/Length |
| NotSupportedException | シーク/読み取り/書き込み不可のストリームへの操作 |
| ObjectDisposedException | 閉じられたストリームへの操作 |
| IOException | Win32 APIエラー、Appendモードでの位置制限違反 |
| InvalidOperationException | タイムアウト操作（サポートされていない） |

---

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

### 7.1 バッファリング
- デフォルトバッファサイズは指定可能（最小8バイト）
- 連続した読み取り/書き込みでバッファを活用
- 読み取りと書き込みの切り替え時にFlush

### 7.2 推奨事項
- 大量のデータを扱う場合は大きなバッファサイズを指定
- 頻繁なFlushは避ける（パフォーマンス低下）
- シーケンシャルアクセスが多い場合に最適

---

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

### 8.1 推奨読解順序

1. **データ構造の理解**
   - `FileStream.cls` 116-130行目: メンバ変数定義
   - 79-114行目: FileMode, FileAccess, FileShare列挙型

2. **初期化処理**
   - `Init` (839-882行目): ファイルパスからの初期化
   - `InitWithHandle` (884-902行目): ハンドルからの初期化

3. **基本操作**
   - `ReadByte` (449-469行目): 1バイト読み取り
   - `ReadBlock` (479-530行目): 複数バイト読み取り
   - `WriteByte` (605-622行目): 1バイト書き込み
   - `WriteBlock` (633-673行目): 複数バイト書き込み

4. **内部アルゴリズム**
   - `FillBuffer` (936-950行目): バッファ充填
   - `InternalSeek` (952-970行目): ファイルポインタ移動
   - `Flush` (739-753行目): バッファフラッシュ

5. **ヘルパーメソッド**
   - `VerifyCanRead` (930-934行目): 読み取り可能性検証
   - `VerifyCanWrite` (924-928行目): 書き込み可能性検証
   - `VerifyCanSeek` (912-916行目): シーク可能性検証
   - `VerifyIsOpen` (918-922行目): オープン状態検証

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

```
FileStream.Init
  ├── CorString.Trim (パス検証)
  ├── Path.GetFullPath (フルパス取得)
  ├── SafeCreateFile (ファイルオープン)
  ├── GetFileType (ファイルタイプ確認)
  └── InternalSeek (Appendモード時)

FileStream.ReadBlock
  ├── ValidateArrayRange
  ├── VerifyCanRead
  ├── VerifyIsOpen
  ├── Flush (書き込みデータがある場合)
  ├── FillBuffer
  │     └── ReadFile API
  └── CopyMemory / ReadFile API

FileStream.WriteBlock
  ├── ValidateArrayRange
  ├── VerifyCanWrite
  ├── VerifyIsOpen
  ├── InternalSeek (読み取りバッファがある場合)
  ├── Flush
  │     └── WriteFile API
  └── CopyMemory / WriteFile API
```

### 8.3 データフロー図

```
[ユーザーデータ]
      │
      ↓
[WriteBlock] ──→ [mBuffer] ──→ [Flush] ──→ [WriteFile API] ──→ [ファイル]
                    ↑
                    │
              [バッファサイズ
               超過時は直接]
                    │
                    ↓
            [WriteFile API]

[ファイル] ──→ [ReadFile API] ──→ [FillBuffer] ──→ [mBuffer] ──→ [ReadBlock] ──→ [ユーザーデータ]
```

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

| パス | 種別 | 役割 |
|------|------|------|
| Source/CorLib/System.IO/FileStream.cls | クラス | メインクラス |
| Source/CorLib/System.IO/Stream.cls | インターフェース | ストリーム基底 |
| Source/CorLib/System.IO/SafeFileHandle.cls | クラス | ハンドル管理 |
| Source/CorLib/System.IO/StreamAsyncResult.cls | クラス | 非同期結果 |
| Source/CorLib/System.IO/IOError.bas | モジュール | I/Oエラー処理 |
| Source/CorLib/System.IO/Path.cls | クラス | パス操作 |

### 8.5 読解のコツ
- Currency型は64ビット整数として使用（VB6の制限回避）
- `0.0001@`の乗算/除算はCurrency↔Long変換のトリック
- DLong構造体は64ビット値を2つの32ビット値で表現
- Appendモードでは`mMinPosition`で書き込み可能範囲を制限
- `mBufferOffset`はバッファがファイル内のどの位置から始まるかを示す

---

## 9. 変更履歴

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

---

## 10. 備考

- .NET FrameworkのSystem.IO.FileStreamと互換性のあるAPI設計
- 非同期操作は現在同期的に実装されている（将来の拡張用）
- パイプやメールスロットのハンドルもラップ可能（シーク不可）
- タイムアウト操作はサポートされていない（InvalidOperationException）
- Currency型を使用して64ビットファイルサイズに対応
