【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);
}
動作解説
- 入力ファイルを開く:
fopen()
で読み取り専用で開きます。 - データの圧縮:連続する文字をカウントし、
count + character
形式で出力します。 - 出力ファイルに保存:圧縮結果をファイルに保存します。
- ファイルを閉じる:開いたすべてのファイルを閉じます。
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);
}
動作解説
- 圧縮ファイルを開く:
fopen()
で読み取り専用で開きます。 - データの展開:
fscanf()
でcount + character
形式のデータを読み取り、文字を展開します。 - 元のデータを保存:展開結果をファイルに保存します。
- ファイルを閉じる:開いたすべてのファイルを閉じます。
3. 練習問題
以下の課題に挑戦して、圧縮アルゴリズムのスキルを向上させましょう。
- RLE圧縮で空白や特殊文字も圧縮できるように改良してください。
- 圧縮後のデータを効率よく保存するために、バイナリ形式で圧縮データを保存するプログラムを作成してください。
- 圧縮率(元データのサイズと圧縮データのサイズの比率)を計算して表示する機能を追加してください。
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. まとめ
本記事では、簡単なランレングス圧縮とその解凍方法を学びました。これらの技術を応用することで、データ管理の効率化が期待できます。