ソースコードから理解する技術-UnderSourceCode

手を動かす(プログラムを組む)ことで技術を理解するブログ

Golangで2つのgzファイルを連結してみる

gzファイルはコマンドだと以下のように連結することができます。

cat sample1.gz sample2.gz > result.gz

これと同じようにgzファイルを連結する処理をGolangで書いてみました。
検索すれば似たようなことをやっている記事は沢山出てくるかと思いますが、備忘録替わりに載せておきます。

ソースについて

「sample1.json.gz」「sample2.json.gz」というgzファイルをあらかじめ用意しておき、実行すると中身が連結されて「result.json.gz」というファイルに出力されます。
今回はファイルの中身をjsonとしたのですが、特にjson形式を解析して何かを行っているわけではないので、中身の形式は問わないと思います。

ソースは以下になりますが、io.Copy()を使ってio.Readerをio.Writerにコピーしているところや、io.WriterのWrite()で改行を書き込んでいるところなどは
Golangのio周りを意識するのにちょうど良かったように感じました。

package main

import (
	"compress/gzip"
	"fmt"
	"io"
	"log"
	"os"
)

func write(zr1 *gzip.Reader, zr2 *gzip.Reader) error {
	writeFile, err := os.OpenFile("./result.json.gz", os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		return err
	}
	defer writeFile.Close()

	zw := gzip.NewWriter(writeFile)
	defer zw.Close()

	_, err = io.Copy(zw, zr1)
	if err != nil {
		return err
	}

	_, err = zw.Write([]byte("\n"))
	if err != nil {
		return err
	}

	_, err = io.Copy(zw, zr2)
	if err != nil {
		return err
	}

	return nil
}

func main() {
	readFile1, err := os.Open("./sample1.json.gz")
	if err != nil {
		log.Fatal(err)
	}
	defer readFile1.Close()

	zr1, err := gzip.NewReader(readFile1)
	if err != nil {
		log.Fatal(err)
	}
	defer zr1.Close()

	readFile2, err := os.Open("./sample2.json.gz")
	if err != nil {
		log.Fatal(err)
	}
	defer readFile2.Close()

	zr2, err := gzip.NewReader(readFile2)
	if err != nil {
		log.Fatal(err)
	}
	defer zr2.Close()

	err = write(zr1, zr2)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("-----finish-----")
}