# 機能設計書: System.IO.Compression（圧縮）

## 1. 機能概要

### 1.1 機能名
System.IO.Compression（圧縮）

### 1.2 機能ID
FUNC-018

### 1.3 機能説明
.NET ランタイムにおけるデータ圧縮・展開機能を提供するライブラリ。DEFLATE、GZip、Brotli、ZLibアルゴリズムによるストリーム圧縮、およびZIPアーカイブの作成・展開機能を提供する。Stream ベースの API により、メモリ効率の良い圧縮処理を実現する。

### 1.4 関連画面
- なし（基盤ライブラリのため直接的な関連画面は存在しない）

## 2. 機能要件

### 2.1 入力仕様

| 項目名 | データ型 | 必須 | 説明 |
|--------|----------|------|------|
| stream | Stream | Yes | 圧縮/展開対象のストリーム |
| mode | CompressionMode | Yes | 圧縮または展開モード |
| compressionLevel | CompressionLevel | No | 圧縮レベル |
| leaveOpen | bool | No | 基底ストリームをオープンのまま保持 |
| archivePath | string | No | ZIPアーカイブパス |

### 2.2 出力仕様

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| Stream | Stream | 圧縮/展開ストリーム |
| ZipArchive | ZipArchive | ZIPアーカイブオブジェクト |
| ZipArchiveEntry | ZipArchiveEntry | アーカイブエントリ |

### 2.3 処理フロー（GZip圧縮）

```
元データストリーム
    │
    ▼
┌─────────────────────┐
│ GZipStream作成       │
│ CompressionMode.    │
│ Compress            │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│ DeflateStream       │
│ (内部委譲)          │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│ ZLib ネイティブ      │
│ 圧縮処理            │
└─────────────────────┘
    │
    ▼
圧縮データストリーム
```

## 3. 詳細設計

### 3.1 クラス構成

#### 3.1.1 圧縮ストリーム

| クラス名 | 責務 |
|----------|------|
| DeflateStream | DEFLATE 圧縮/展開 |
| GZipStream | GZip 圧縮/展開（DEFLATE + GZip ヘッダー） |
| BrotliStream | Brotli 圧縮/展開 |
| ZLibStream | ZLib 圧縮/展開 |

#### 3.1.2 ZIPアーカイブ

| クラス名 | 責務 |
|----------|------|
| ZipArchive | ZIPアーカイブの読み書き |
| ZipArchiveEntry | アーカイブ内エントリ |
| ZipFile | 静的ヘルパーメソッド |

### 3.2 GZipStream クラス（GZipStream.cs）

#### 3.2.1 コンストラクタ

```csharp
// GZipStream.cs: 15-22行目
public GZipStream(Stream stream, CompressionMode mode)
    : this(stream, mode, leaveOpen: false)
{
}

public GZipStream(Stream stream, CompressionMode mode, bool leaveOpen)
{
    _deflateStream = new DeflateStream(stream, mode, leaveOpen, ZLibNative.GZip_DefaultWindowBits);
}

// 圧縮レベル指定（GZipStream.cs: 24-33行目）
public GZipStream(Stream stream, CompressionLevel compressionLevel)
    : this(stream, compressionLevel, leaveOpen: false)
{
}

public GZipStream(Stream stream, CompressionLevel compressionLevel, bool leaveOpen)
{
    _deflateStream = new DeflateStream(stream, compressionLevel, leaveOpen, ZLibNative.GZip_DefaultWindowBits);
}

// 詳細オプション指定（GZipStream.cs: 42-45行目）
public GZipStream(Stream stream, ZLibCompressionOptions compressionOptions, bool leaveOpen = false)
{
    _deflateStream = new DeflateStream(stream, compressionOptions, leaveOpen, ZLibNative.GZip_DefaultWindowBits);
}
```

#### 3.2.2 ストリームプロパティ

```csharp
// GZipStream.cs: 47-62行目
public override bool CanRead => _deflateStream?.CanRead ?? false;
public override bool CanWrite => _deflateStream?.CanWrite ?? false;
public override bool CanSeek => _deflateStream?.CanSeek ?? false;

public override long Length
{
    get { throw new NotSupportedException(SR.NotSupported); }
}

public override long Position
{
    get { throw new NotSupportedException(SR.NotSupported); }
    set { throw new NotSupportedException(SR.NotSupported); }
}
```

#### 3.2.3 読み書きメソッド

```csharp
// GZipStream.cs: 80-112行目
public override int ReadByte()
{
    CheckDeflateStream();
    return _deflateStream.ReadByte();
}

public override int Read(byte[] buffer, int offset, int count)
{
    CheckDeflateStream();
    return _deflateStream.Read(buffer, offset, count);
}

public override int Read(Span<byte> buffer)
{
    // 派生クラス対応のための分岐
    if (GetType() != typeof(GZipStream))
    {
        return base.Read(buffer);
    }
    else
    {
        CheckDeflateStream();
        return _deflateStream.ReadCore(buffer);
    }
}

// 書き込み（GZipStream.cs: 120-156行目）
public override void Write(byte[] buffer, int offset, int count)
{
    CheckDeflateStream();
    _deflateStream.Write(buffer, offset, count);
}

public override void Write(ReadOnlySpan<byte> buffer)
{
    if (GetType() != typeof(GZipStream))
    {
        base.Write(buffer);
    }
    else
    {
        CheckDeflateStream();
        _deflateStream.WriteCore(buffer);
    }
}
```

#### 3.2.4 非同期メソッド

```csharp
// GZipStream.cs: 206-248行目
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
    CheckDeflateStream();
    return _deflateStream.ReadAsync(buffer, offset, count, cancellationToken);
}

public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
    if (GetType() != typeof(GZipStream))
    {
        return base.ReadAsync(buffer, cancellationToken);
    }
    else
    {
        CheckDeflateStream();
        return _deflateStream.ReadAsyncMemory(buffer, cancellationToken);
    }
}

public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
    CheckDeflateStream();
    return _deflateStream.WriteAsync(buffer, offset, count, cancellationToken);
}

public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
    if (GetType() != typeof(GZipStream))
    {
        return base.WriteAsync(buffer, cancellationToken);
    }
    else
    {
        CheckDeflateStream();
        return _deflateStream.WriteAsyncMemory(buffer, cancellationToken);
    }
}
```

#### 3.2.5 BaseStreamプロパティ

```csharp
// GZipStream.cs: 197-204行目
public Stream BaseStream
{
    get
    {
        CheckDeflateStream();
        return _deflateStream.BaseStream;
    }
}
```

### 3.3 CompressionMode 列挙型

| モード | 値 | 説明 |
|--------|-----|------|
| Decompress | 0 | 展開 |
| Compress | 1 | 圧縮 |

### 3.4 CompressionLevel 列挙型

| レベル | 値 | 説明 |
|--------|-----|------|
| Optimal | 0 | 最適な圧縮率 |
| Fastest | 1 | 最速（低圧縮率） |
| NoCompression | 2 | 圧縮なし |
| SmallestSize | 3 | 最小サイズ（最高圧縮率） |

### 3.5 ZipArchive クラス

#### 3.5.1 コンストラクタ

```csharp
public ZipArchive(Stream stream);
public ZipArchive(Stream stream, ZipArchiveMode mode);
public ZipArchive(Stream stream, ZipArchiveMode mode, bool leaveOpen);
public ZipArchive(Stream stream, ZipArchiveMode mode, bool leaveOpen, Encoding? entryNameEncoding);
```

#### 3.5.2 主要メソッド

```csharp
// エントリ作成
public ZipArchiveEntry CreateEntry(string entryName);
public ZipArchiveEntry CreateEntry(string entryName, CompressionLevel compressionLevel);

// エントリ取得
public ZipArchiveEntry? GetEntry(string entryName);

// プロパティ
public ReadOnlyCollection<ZipArchiveEntry> Entries { get; }
public ZipArchiveMode Mode { get; }
```

### 3.6 ZipFile 静的クラス

```csharp
// アーカイブ作成
public static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName);
public static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName, CompressionLevel compressionLevel, bool includeBaseDirectory);

// アーカイブ展開
public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName);
public static void ExtractToDirectory(string sourceArchiveFileName, string destinationDirectoryName, bool overwriteFiles);

// アーカイブオープン
public static ZipArchive Open(string archiveFileName, ZipArchiveMode mode);
public static ZipArchive OpenRead(string archiveFileName);
```

### 3.7 ZipArchiveMode 列挙型

| モード | 値 | 説明 |
|--------|-----|------|
| Read | 0 | 読み取り専用 |
| Create | 1 | 作成専用 |
| Update | 2 | 更新（読み書き） |

## 4. エラー処理

### 4.1 例外一覧

| 例外 | 発生条件 |
|------|----------|
| InvalidDataException | 圧縮データが不正 |
| NotSupportedException | 未サポートの操作（Length, Position等） |
| ObjectDisposedException | Dispose後の操作 |
| ArgumentNullException | ストリームがnull |
| ArgumentException | 引数が不正 |
| IOException | I/Oエラー |

### 4.2 状態チェック

```csharp
// GZipStream.cs: 262-265行目
private void CheckDeflateStream()
{
    ObjectDisposedException.ThrowIf(_deflateStream is null, this);
}
```

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

### 5.1 ZIP爆弾対策
- 展開サイズの制限を推奨
- 深いディレクトリネストの制限
- エントリ数の制限

### 5.2 パストラバーサル
- ZIPエントリ名の検証
- 相対パスの適切な処理

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

### 6.1 推奨読解順序

1. **エントリーポイント**
   - `GZipStream.cs`: GZip圧縮の主要クラス
   - **15-45行目**: コンストラクタ群
   - **47-62行目**: ストリームプロパティ
   - **80-112行目**: 読み取りメソッド
   - **120-156行目**: 書き込みメソッド

2. **内部実装**
   - `DeflateStream.cs`: 実際の圧縮処理
   - `ZLibNative.cs`: ネイティブZLib呼び出し

3. **ZIPアーカイブ**
   - `ZipArchive.cs`: アーカイブ管理
   - `ZipArchiveEntry.cs`: エントリ管理
   - `ZipFile.cs`: 静的ヘルパー

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

```
new GZipStream(stream, CompressionMode.Compress)
    │
    └── new DeflateStream(stream, mode, leaveOpen, GZip_DefaultWindowBits)
            │
            ├── Deflater/Inflater作成
            │
            └── ZLib初期化

gzipStream.Write(buffer)
    │
    ├── CheckDeflateStream()
    │
    └── _deflateStream.Write(buffer)
            │
            └── WriteCore(buffer)
                    │
                    ├── Deflater.SetInput(buffer)
                    │
                    ├── while (!Deflater.NeedsInput())
                    │       │
                    │       └── Deflater.Deflate()
                    │               │
                    │               └── ZLib.deflate()
                    │
                    └── BaseStream.Write(compressed)
```

### 6.3 データフロー図

```
┌──────────────────┐
│ 元データ          │
│ byte[]           │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ GZipStream       │
│ GZipヘッダー追加  │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ DeflateStream    │
│ DEFLATE圧縮      │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ Deflater         │
│ ZLib呼び出し      │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ 圧縮データ        │
│ + GZipトレーラー  │
└──────────────────┘
```

### 6.4 読解のコツ

#### 6.4.1 派生クラス対応パターン
GZipStreamは継承可能なため、派生クラスで旧メソッドがオーバーライドされている可能性に対応:
```csharp
public override int Read(Span<byte> buffer)
{
    if (GetType() != typeof(GZipStream))
    {
        return base.Read(buffer);  // 派生クラス用
    }
    else
    {
        return _deflateStream.ReadCore(buffer);  // 直接呼び出し
    }
}
```

#### 6.4.2 DeflateStreamへの委譲
GZipStreamは内部でDeflateStreamをラップ:
- GZipヘッダー/トレーラーの追加
- 実際の圧縮処理はDeflateStreamが担当

#### 6.4.3 WindowBitsパラメータ
`ZLibNative.GZip_DefaultWindowBits`でGZipフォーマットを指定:
- 正の値: raw DEFLATE
- 負の値: raw DEFLATE (ヘッダーなし)
- +16: GZipフォーマット
- +32: 自動検出

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

| パス | 種別 | 役割 |
|------|------|------|
| `src/libraries/System.IO.Compression/src/System/IO/Compression/GZipStream.cs` | ソース | GZip圧縮 |
| `src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateStream.cs` | ソース | DEFLATE圧縮 |
| `src/libraries/System.IO.Compression/src/System/IO/Compression/BrotliStream.cs` | ソース | Brotli圧縮 |
| `src/libraries/System.IO.Compression/src/System/IO/Compression/ZLibStream.cs` | ソース | ZLib圧縮 |
| `src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipArchive.cs` | ソース | ZIPアーカイブ |
| `src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipArchiveEntry.cs` | ソース | ZIPエントリ |
| `src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFile.cs` | ソース | 静的ヘルパー |

## 7. 使用例

### 7.1 GZip圧縮

```csharp
// 圧縮
using (var output = File.Create("data.gz"))
using (var gzip = new GZipStream(output, CompressionLevel.Optimal))
{
    gzip.Write(data);
}

// 展開
using (var input = File.OpenRead("data.gz"))
using (var gzip = new GZipStream(input, CompressionMode.Decompress))
using (var ms = new MemoryStream())
{
    gzip.CopyTo(ms);
    byte[] decompressed = ms.ToArray();
}
```

### 7.2 ZIPアーカイブ作成

```csharp
// ディレクトリからZIP作成
ZipFile.CreateFromDirectory("source_folder", "archive.zip");

// 手動作成
using (var archive = ZipFile.Open("archive.zip", ZipArchiveMode.Create))
{
    archive.CreateEntryFromFile("file.txt", "entry.txt", CompressionLevel.Optimal);
}
```

### 7.3 ZIPアーカイブ展開

```csharp
// ディレクトリへ展開
ZipFile.ExtractToDirectory("archive.zip", "output_folder");

// 手動展開
using (var archive = ZipFile.OpenRead("archive.zip"))
{
    foreach (var entry in archive.Entries)
    {
        entry.ExtractToFile(Path.Combine("output", entry.Name));
    }
}
```

### 7.4 Brotli圧縮

```csharp
// 圧縮
using (var output = File.Create("data.br"))
using (var brotli = new BrotliStream(output, CompressionLevel.Optimal))
{
    brotli.Write(data);
}
```

## 8. テスト観点

### 8.1 単体テスト観点
- 圧縮・展開の往復一致
- 各CompressionLevelでの動作
- 大きなデータの処理
- 空データの処理

### 8.2 結合テスト観点
- 他ツールで作成したファイルとの互換性
- ストリーミング処理の正確性

### 8.3 性能テスト観点
- 圧縮率の測定
- 処理速度の測定
- メモリ使用量

## 9. 変更履歴

| バージョン | 日付 | 変更内容 |
|------------|------|----------|
| 1.0 | 2026-01-30 | 初版作成 |
