clojureでtar.gzファイルにアクセスしてみる
元々はJavaでtar.gzファイルにアクセスする方法を調べていて、Clojureの勉強も兼ねてそっちのコードも書いてみる。
leiningenでプロジェクト作って試していたので、-main関数とかも書いて、引数でファイル名を受け取れるようにしている。
ポイントはloopマクロ、recur辺りかな。
プログラミングClojureを読んでいるときにはloopマクロがイマイチよく分からなかったけど、実際に書いてみると何となく分かった気がする。
(ns sample.core (:gen-class) (:import (org.apache.tools.tar TarInputStream) (java.util.zip GZIPInputStream) (java.io FileInputStream ByteArrayOutputStream))) ;tar.gz内のファイル名をベクタで取得する (defn get-targz-names [file_name] (with-open [file (TarInputStream. (GZIPInputStream. (FileInputStream. file_name)))] (loop [file_list [] entry (.getNextEntry file)] (if (nil? entry) file_list (recur (conj file_list (.getName entry)) (.getNextEntry file)))))) ;tar.gz内のファイルを標準出力に表示する (defn print-targz-file [file_name] (with-open [file (TarInputStream. (GZIPInputStream. (FileInputStream. file_name)))] (loop [entry (.getNextEntry file)] (if (nil? entry) nil (do (let [size (.getSize entry) bos (ByteArrayOutputStream. size)] ;(.copyEntryContents file bos) (. file copyEntryContents bos) (println (String. (.toByteArray bos)))) (recur (.getNextEntry file))))))) (defn -main [& args] (def file_name (first args)) (println (get-targz-names file_name)) (print-targz-file file_name))
leiningenで使うproject.cljファイルはこんな感じ。
TarInputStreamはApache-Antに含まれているので、依存ライブラリとして追加している。
(defproject sample "1.0.0-SNAPSHOT" :description "FIXME: write" :dependencies [[org.clojure/clojure "1.1.0"] [org.clojure/clojure-contrib "1.1.0"] [org.apache.ant/ant "1.8.0"]] :main sample.core)