archive/zipパッケージなるものがあります.
The Go Programming Language - Package zip
使い方
zipアーカイブは複数のファイルが入るので, 1つのio.Writerから複数ファイルのwriterを作成する構成をとっているようです.
- zipWriter(io.Writerから作成)
- writer(zipWriterから作成)
- writer(zipWriterから作成)
- writer(zipWriterから作成)
なので手順としては
- zip.NewWriterへio.Writerを渡してzipWriterを作る
- zipWriterから各ファイルのwriterを作る
- 作ったwriterへファイルの内容を書き込む
となります.
サンプルコード
先に動作を.
こんなフォルダを.
test/ ├── bar.txt ├── foo.txt └── test.txt
こんな感じで圧縮できます.
$ ./sample.exe test.zip test/*
コードは以下の通り.
package main import ( "archive/zip" "fmt" "io" "os" ) func main() { if len(os.Args) < 3 { fmt.Println("Usage: %s [zipname] [src] [src2] ...") return } dest, err := os.Create(os.Args[1]) if err != nil { panic(err) } zipWriter := zip.NewWriter(dest) defer zipWriter.Close() for _, s := range os.Args[2:] { if err := addToZip(s, zipWriter); err != nil { panic(err) } } } func addToZip(filename string, zipWriter *zip.Writer) error { src, err := os.Open(filename) if err != nil { return err } defer src.Close() writer, err := zipWriter.Create(filename) if err != nil { return err } _, err = io.Copy(writer, src) if err != nil { return err } return nil }
感想
たった50行程度でいつも使っているzipができるというのはなかなか感慨深いものがありました.
今度はzipの構成とか調べてみようかな.
余談
io.Writer使ってるんで当たり前ですが, http経由で渡すとか, そんなのも割と簡単に書けます.
package main import ( "archive/zip" "io" "net/http" "os" ) func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } func handler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/zip") w.Header().Set("Content-Disposition", "attachment; filename=test.zip") zipWriter := zip.NewWriter(w) defer zipWriter.Close() for _, s := range os.Args[1:] { if err := addToZip(s, zipWriter); err != nil { panic(err) } } } func addToZip(filename string, zipWriter *zip.Writer) error { src, err := os.Open(filename) if err != nil { return err } defer src.Close() writer, err := zipWriter.Create(filename) if err != nil { return err } _, err = io.Copy(writer, src) if err != nil { return err } return nil }
$ ./sample.exe test/*