1
1

More than 3 years have passed since last update.

Javaでgzipファイルの読み書き

Posted at

はじめに

そのままでサイズ大きいファイルを、gzip圧縮したままでやりとりするケースがあります。
javaでのgzipでのファイルの読み書きを整理しました。Java8のときからのものですが、java11でもいけそうです。

読み込み

csvファイルをgzip圧縮したものを例にします

ポイントは

  1. try-with-resources構文を使う
  2. InputSreamをGZIPInputStreamでラップする
  3. GZIPInputStreamをInputStreamReaderでラップする
  4. InputStreamReaderのときに、エンコーディングを指定できる
  5. InputStreamReaderをBufferedReaderでラップする
Java

Path path = Paths.get("read_test.csv.gz");
try(
  InputStream is = Files.newInputStream(path);
  GZIPInputStream gis = new GZIPInputStream(is);
  InputStreamReader isReader = new InputStreamReader(gis, StandardCharsets.UTF_8);
  BufferedReader br = new BufferedReader(isReader); 
) {
  br.lines().forEach(System.out::println);
}

BufferedReaderでラップするのは性能のためです。
実践では、csv読み込みのライブラリを使うのが通例ですね。
ここではunivocity_parsers を使ったサンプルをあげてみます。

大容量を想定して、iteratorで取り扱う例です。

Path path = Paths.get("read_test.csv.gz");
try(
  InputStream is = Files.newInputStream(path);
  GZIPInputStream gis = new GZIPInputStream(is);
  InputStreamReader isReader = new InputStreamReader(gis, StandardCharsets.UTF_8);
  BufferedReader br = new BufferedReader(isReader); 
) {
  CsvParserSettings parserSettings = new CsvParserSettings();
  CsvRoutines routines = new CsvRoutines(parserSettings);
  Iterator<TestDTO> iterator = routines.iterate(TestDTO.class, br).iterator();
  iterator.forEachRemaining(x -> System.out.println(x.toString()));
}

書き込み

ポイントは読み込みとほぼ同様で

  1. try-with-resources構文を使う
  2. OutputStreamをGZIPOutputStreamでラップする
  3. GZIPOutputStreamをOutputStreamWriterでラップする
  4. OutputStreamWriterでエンコーディングを指定できる
  5. OutputStreamWriterをBufferedWriterでラップする
Path path = Paths.get("write_test.csv.gz");
try (
  OutputStream os = Files.newOutputStream(path,StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
  GZIPOutputStream gzip = new GZIPOutputStream(os);
  OutputStreamWriter ow = new OutputStreamWriter(gzip, StandardCharsets.UTF_8);
  BufferedWriter bw = new BufferedWriter(ow);) {
  List<String> rows = ...;
  rows.stream().forEach(row -> bw.write(row)); 
}  

csvライブラリを使っての書き込みの例はこうなります。

Path path = Paths.get("write_test.csv.gz");
try (
  OutputStream os = Files.newOutputStream(path,StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
  GZIPOutputStream gzip = new GZIPOutputStream(os);
  OutputStreamWriter ow = new OutputStreamWriter(gzip, StandardCharsets.UTF_8);
  BufferedWriter bw = new BufferedWriter(ow);) {
  List<TestDTO> rows = ...;
  CsvWriterSettings writerSettings = new CsvWriterSettings();
  CsvWriter writer = new CsvWriter(bw , writerSettings);
  rows.stream().forEach(rows -> writer.processRecord(row));
}  

所感

やり方がわかればなんてことはないですが、一体、何回オブジェクトをラップすればいいんだ、という感じです。基本的に、csvライブラリにはreader or writerを渡せば、よしなにやってくれることが多いです。その点では、何度もラップした甲斐があるというものです。

参考リンク

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1