C言語

【C言語】第7章第14回:ファイル圧縮アルゴリズムの実装

ファイル圧縮は、データの効率的な保存や転送に欠かせない技術です。本記事では、C言語を使って簡単な圧縮アルゴリズムを実装する方法を学びます。

0. 記事の概要

この記事を読むメリット

  • 圧縮技術の理解:データ圧縮の基本を学べます。
  • 実践的なスキル:圧縮アルゴリズムの基本的な実装スキルを習得できます。
  • 応用力の向上:圧縮技術を応用したデータ管理の効率化が可能になります。

この記事で学べること

  • ランレングス圧縮(RLE)の基礎
  • 圧縮データの解凍方法
  • 圧縮アルゴリズムの応用例

活用のイメージ

例えば、大量のログデータやテキストデータを効率的に保存する際に、圧縮アルゴリズムが役立ちます。

1. ランレングス圧縮(RLE)の基礎

1.1 RLEとは?

ランレングス圧縮(Run-Length Encoding)は、連続する同じデータを簡潔に表現する圧縮手法です。

例:

元データ: AAAABBBCCDAA

圧縮後: 4A3B2C1D2A

1.2 RLEを使った圧縮の実装

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

void compressRLE(const char *input, const char *output) {
    FILE *inFile = fopen(input, "r");
    FILE *outFile = fopen(output, "w");

    if (inFile == NULL || outFile == NULL) {
        perror("Error opening file");
        return;
    }

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

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

    if (count > 0) {
        fprintf(outFile, "%d%c", count, prevChar);
    }

    fclose(inFile);
    fclose(outFile);
    printf("Compression complete. Output saved to %s\n", output);
}
動作解説
  1. 入力ファイルを開く:fopen()で読み取り専用で開きます。
  2. データの圧縮:連続する文字をカウントし、count + character形式で出力します。
  3. 出力ファイルに保存:圧縮結果をファイルに保存します。
  4. ファイルを閉じる:開いたすべてのファイルを閉じます。

2. 圧縮データの解凍

2.1 解凍の基本

圧縮データを元の形式に戻すために、データの解析と展開を行います。

2.2 解凍プログラムの実装

#include <stdio.h>

void decompressRLE(const char *input, const char *output) {
    FILE *inFile = fopen(input, "r");
    FILE *outFile = fopen(output, "w");

    if (inFile == NULL || outFile == NULL) {
        perror("Error opening file");
        return;
    }

    int count;
    char character;

    while (fscanf(inFile, "%d%c", &count, &character) == 2) {
        for (int i = 0; i < count; i++) {
            fputc(character, outFile);
        }
    }

    fclose(inFile);
    fclose(outFile);
    printf("Decompression complete. Output saved to %s\n", output);
}
動作解説
  1. 圧縮ファイルを開く:fopen()で読み取り専用で開きます。
  2. データの展開:fscanf()count + character形式のデータを読み取り、文字を展開します。
  3. 元のデータを保存:展開結果をファイルに保存します。
  4. ファイルを閉じる:開いたすべてのファイルを閉じます。

3. 練習問題

以下の課題に挑戦して、圧縮アルゴリズムのスキルを向上させましょう。

  1. RLE圧縮で空白や特殊文字も圧縮できるように改良してください。
  2. 圧縮後のデータを効率よく保存するために、バイナリ形式で圧縮データを保存するプログラムを作成してください。
  3. 圧縮率(元データのサイズと圧縮データのサイズの比率)を計算して表示する機能を追加してください。

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

問3の解答

#include <stdio.h>

void calculateCompressionRatio(const char *original, const char *compressed) {
    FILE *origFile = fopen(original, "r");
    FILE *compFile = fopen(compressed, "r");

    if (origFile == NULL || compFile == NULL) {
        perror("Error opening file");
        return;
    }

    fseek(origFile, 0, SEEK_END);
    fseek(compFile, 0, SEEK_END);

    long origSize = ftell(origFile);
    long compSize = ftell(compFile);

    rewind(origFile);
    rewind(compFile);

    printf("Original size: %ld bytes\n", origSize);
    printf("Compressed size: %ld bytes\n", compSize);
    printf("Compression ratio: %.2f%%\n", (1.0 - (double)compSize / origSize) * 100);

    fclose(origFile);
    fclose(compFile);
}

このプログラムでは、元データと圧縮データのサイズを比較して圧縮率を計算します。

5. まとめ

本記事では、簡単なランレングス圧縮とその解凍方法を学びました。これらの技術を応用することで、データ管理の効率化が期待できます。