C言語

【C言語】第10章第4回:ファイル圧縮ツールの作成

C言語を使って、シンプルなファイル圧縮ツールを作成します。本記事では、基本的なデータ圧縮アルゴリズムとその実装方法を学びます。

0. 記事の概要

この記事を読むメリット

  • データ圧縮の基本理解:簡単な圧縮アルゴリズムの実装を通じて、圧縮の仕組みを学べます。
  • ファイル操作スキルの向上:ファイルの読み書きとデータ操作を組み合わせた応用力を養います。
  • プログラムの応用可能性:圧縮アルゴリズムを拡張して、より高度なツールを開発できます。

この記事で学べること

  • シンプルなデータ圧縮アルゴリズム
  • ファイルの読み書き処理
  • アルゴリズムの効率性を考慮したプログラム設計

1. ファイル圧縮ツールの基本設計

1.1 圧縮ツールの機能

このツールでは、以下の基本機能を実装します。

  • テキストファイルの圧縮
  • 圧縮ファイルの解凍
  • アルゴリズムの効率化(ランレングス圧縮法を使用)

1.2 ランレングス圧縮法とは?

ランレングス圧縮法(Run-Length Encoding: RLE)は、連続する同じデータをそのデータの値と繰り返し回数に置き換える手法です。

例:
入力: AAAABBBCCDAA
出力: A4B3C2D1A2

1.3 必要なプログラム構造

プログラムは以下の主要部分で構成されます。

  • ファイルの読み込み
  • データの圧縮処理
  • 圧縮結果の保存と解凍処理

2. コード例と詳細解説

2.1 基本コード例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 圧縮処理
void compressFile(const char *inputFile, const char *outputFile) {
    FILE *in = fopen(inputFile, "r");
    FILE *out = fopen(outputFile, "w");

    if (!in || !out) {
        printf("ファイルを開けませんでした。\\n");
        return;
    }

    char currentChar, prevChar = '\0';
    int count = 0;

    while ((currentChar = fgetc(in)) != EOF) {
        if (currentChar == prevChar) {
            count++;
        } else {
            if (count > 0) {
                fprintf(out, "%c%d", prevChar, count);
            }
            prevChar = currentChar;
            count = 1;
        }
    }
    if (count > 0) {
        fprintf(out, "%c%d", prevChar, count);
    }

    fclose(in);
    fclose(out);
    printf("圧縮が完了しました。\\n");
}

// 解凍処理
void decompressFile(const char *inputFile, const char *outputFile) {
    FILE *in = fopen(inputFile, "r");
    FILE *out = fopen(outputFile, "w");

    if (!in || !out) {
        printf("ファイルを開けませんでした。\\n");
        return;
    }

    char ch;
    int count;
    while (fscanf(in, "%c%d", &ch, &count) == 2) {
        for (int i = 0; i < count; i++) {
            fputc(ch, out);
        }
    }

    fclose(in);
    fclose(out);
    printf("解凍が完了しました。\\n");
}

int main() {
    char inputFile[100], outputFile[100];
    int choice;

    printf("ファイル圧縮ツールへようこそ!\\n");
    printf("1. 圧縮\\n");
    printf("2. 解凍\\n");
    printf("選択してください: ");
    scanf("%d", &choice);

    printf("入力ファイル名を入力してください: ");
    scanf("%s", inputFile);
    printf("出力ファイル名を入力してください: ");
    scanf("%s", outputFile);

    if (choice == 1) {
        compressFile(inputFile, outputFile);
    } else if (choice == 2) {
        decompressFile(inputFile, outputFile);
    } else {
        printf("無効な選択です。\\n");
    }

    return 0;
}
動作解説
  1. 圧縮処理:`compressFile`関数でランレングス圧縮を実行し、結果をファイルに保存します。
  2. 解凍処理:`decompressFile`関数で圧縮データを元の形式に戻します。
  3. ユーザーインターフェース:`scanf`でユーザーからファイル名や処理の選択を取得します。

3. 練習問題

以下の課題に挑戦して、ファイル圧縮ツールを拡張してみましょう。

  1. 圧縮アルゴリズムを改良して、文字列だけでなくバイナリデータにも対応できるようにしてください。
  2. 圧縮率を計算して、圧縮前後のサイズを表示してください。
  3. 圧縮データにエラーチェック機能を追加して、解凍時にデータの正確性を確認してください。

4. 練習問題の解答と解説

問2の解答例

// 圧縮率の計算
void calculateCompressionRatio(const char *inputFile, const char *outputFile) {
    FILE *in = fopen(inputFile, "r");
    FILE *out = fopen(outputFile, "r");

    if (!in || !out) {
        printf("ファイルを開けませんでした。\\n");
        return;
    }

    fseek(in, 0, SEEK_END);
    long inputSize = ftell(in);
    fclose(in);

    fseek(out, 0, SEEK_END);
    long outputSize = ftell(out);
    fclose(out);

    printf("圧縮前のサイズ: %ld bytes\\n", inputSize);
    printf("圧縮後のサイズ: %ld bytes\\n", outputSize);
    printf("圧縮率: %.2f%%\\n", ((double)(inputSize - outputSize) / inputSize) * 100);
}

このプログラムでは、圧縮前後のサイズを計算し、圧縮率を出力します。

5. まとめ

本記事では、C言語を用いたファイル圧縮ツールの基本的な作成方法を解説しました。さらに高度なアルゴリズムを導入して、実用的なツールに進化させてみましょう。