gzip圧縮ユーティリティは何のために必要なのか
業務システムでは、ログ、CSV、JSON、バックアップファイルなど「サイズが大きくなりがちなデータ」を扱う場面が多くあります。 そのまま保存するとディスクを圧迫し、ネットワーク転送にも時間がかかります。 そこで役に立つのが gzip圧縮 です。
gzipは「高速・軽量・広く使われている」圧縮方式で、Java 標準ライブラリだけで簡単に扱えます。 初心者がつまずきやすいポイントは、 「ストリームをどうつなぐか」「どこで閉じるか」「バイトと文字列の境界をどう扱うか」 といった部分です。
ここから、実務で使える形に噛み砕いて解説します。
gzip圧縮の基本:GZIPOutputStream を使う
圧縮したいデータを OutputStream に流すだけ
Java では、gzip圧縮は GZIPOutputStream を使うだけで実現できます。 「OutputStream に流したデータが gzip 形式で書き出される」という仕組みです。
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.zip.GZIPOutputStream;
public class GzipUtils {
public static void compress(Path input, Path output) throws IOException {
try (OutputStream out = new GZIPOutputStream(Files.newOutputStream(output))) {
byte[] bytes = Files.readAllBytes(input);
out.write(bytes);
}
}
}
Java使い方の例です。
Path input = Path.of("data/report.csv");
Path output = Path.of("data/report.csv.gz");
GzipUtils.compress(input, output);
Javaここで深掘りしたいポイントは 「GZIPOutputStream は OutputStream の一種」 ということです。 つまり、OutputStream out = new GZIPOutputStream(...) としておけば、 out.write() に流したバイトが自動的に gzip 形式に変換されます。
gzip解凍の基本:GZIPInputStream を使う
圧縮されたデータを InputStream から読み出すだけ
解凍は GZIPInputStream を使います。 「InputStream から読み出したデータが自動的に解凍される」という仕組みです。
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.zip.GZIPInputStream;
public class GzipUtils {
public static void decompress(Path input, Path output) throws IOException {
try (InputStream in = new GZIPInputStream(Files.newInputStream(input))) {
byte[] bytes = in.readAllBytes();
Files.write(output, bytes);
}
}
}
Java使い方の例です。
Path input = Path.of("data/report.csv.gz");
Path output = Path.of("data/report.csv");
GzipUtils.decompress(input, output);
Javaここで深掘りしたいポイントは 「GZIPInputStream は InputStream の一種」 ということです。 つまり、in.read() で読み出したバイトはすでに解凍済みです。
ストリームコピーと組み合わせると強力になる
大きなファイルは「readAllBytes」ではなくストリームで流す
先ほどの例はシンプルですが、巨大ファイルでは readAllBytes() がメモリを圧迫します。 そこで、gzip圧縮とストリームコピーを組み合わせます。
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.zip.GZIPOutputStream;
public class GzipStreamUtils {
public static void compressStream(Path input, Path output) throws Exception {
try (InputStream in = Files.newInputStream(input);
OutputStream out = new GZIPOutputStream(Files.newOutputStream(output))) {
byte[] buffer = new byte[8192];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
}
}
}
Javaここで深掘りしたいポイントは 「部分読み込みと部分書き込み」 です。
in.read(buffer) は「バッファサイズぴったり読める」とは限らず、 実際に読めたバイト数(len)を返します。
必ず out.write(buffer, 0, len) として「有効な範囲だけ」書き出す必要があります。 これを怠ると、gzipファイルが壊れます。
gzip圧縮と文字列の扱い
テキストを圧縮するときは「文字コード」を必ず指定する
CSV や JSON を gzip圧縮する場合、 「文字列 → バイト列 → gzip」という流れになります。
String text = "こんにちは、MONOさん!";
byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
Javaここで深掘りしたいポイントは 「文字コードを必ず指定する」 ことです。 getBytes() を文字コードなしで呼ぶと、環境依存になり、 本番と検証環境で結果が変わる危険があります。
gzip圧縮の実務的な使いどころ
ログ・CSV・JSON の圧縮保存
ログやCSVはサイズが大きくなりがちなので、 「保存時に gzip圧縮する」だけでディスク使用量を大幅に削減できます。
HTTPレスポンスの gzip圧縮(Web API)
Web API では、レスポンスを gzip圧縮して返すことで通信量を減らせます。 Java の Web フレームワークは多くが自動対応していますが、 自前でやる場合は GZIPOutputStream を使います。
バックアップファイルの圧縮
設定ファイルやデータファイルをバックアップするとき、 gzip圧縮しておくと保存容量が減り、転送も高速になります。
セキュリティ・運用の観点から見た gzip圧縮
圧縮ファイルの「展開先」を必ず制御する
gzip解凍は「展開先のパス」を指定する必要があります。 外部入力からパスをそのまま受け取ると、 ディレクトリトラバーサル攻撃(../../etc/passwd)の危険があります。
必ず「許可されたディレクトリ配下に限定する」設計にしてください。
圧縮ファイルのサイズに注意する(ZIP爆弾)
gzipはZIPほど危険ではありませんが、 「圧縮前は巨大なデータ」を送りつける攻撃は存在します。
解凍前にサイズチェックを行う、 ストリームで少しずつ処理する、 といった対策が有効です。
まとめ:gzip圧縮ユーティリティで身につけてほしい感覚
gzip圧縮ユーティリティは、 「バイト列を効率よく圧縮・解凍する」ための小さな道具です。
その裏には次のような大事なポイントがあります。
GZIPOutputStream を使えば、書き込むだけで自動圧縮される。 GZIPInputStream を使えば、読み出すだけで自動解凍される。 巨大ファイルは ストリームコピー と組み合わせる。 文字列を圧縮する場合は UTF-8 を必ず指定する。 解凍時のパス制御やサイズチェックなど、セキュリティも意識する。
もしあなたのプロジェクトで、 「CSVをそのまま保存してディスクが圧迫されている」 「ログが巨大化して困っている」 「APIレスポンスが重い」 といった課題があるなら、gzip圧縮ユーティリティを導入する価値があります。
