Google guava………便利だよね。Appache Common………便利だよね。
………まぁ、デカいとは言わないけど、ちりも積もればなんとやらだよね?
………でかすぎね?
そう、私は言いたいのだ。世の便利なJarファイルはデカい。デカすぎる。
ちょっとした内製ツールをウッカリ慣れてるJavaやClojureで作ってしまって、他の人達が単体で使える様に共有サーバー(遅い)へzipして置くと、なんだかんだ言って容量を食うのだ。今、この文章を打った時に、「なんだかんだ言って面積を食うのだ」と書いてしまった私は論理に毒されてきている気がするぞ。
果たしてGoogle guavaの一体どれほどのクラスを使ったことがあろうか。Appache Common IOのどれほどを使ったことがあろうか。Eclipse Collectionの、ホゲホゲの、モゲモゲの、ピヨピヨの世に数多あるライブラリの一体何パーセントを使っているというのだ。恐らく数kb分しか使ってない。そのために100kb?ウンMb?肩身が狭い!
github.com.nodamushi:common.paths
と、私が叫んでいると言うことは、案外同じ事思ってる人って居るんじゃねぇの?ってことで、普段よく使ってるPathに関する関数を集めて、まとめてみた。GitHub - nodamushi/common.paths: A small utilities for java.nio.file.Path.
コンセプトは地味でコンパクトだ。
クラスは内部クラスを除けば地味に一個しかない。Jarファイルは地味に13kbyte。まぁ、これぐらいなら地味に許されてもいいんじゃないだろうか?
あと、地味にnio.Pathをそのまま使うライブラリってあまりない気がする。Stringか、Fileだよね。
地味にMavenに置いた
私が作った物使う阿呆いねぇだろ、ってことで、何か作ってもソースコード公開するだけで放置がデフォルトなんだけど、今回のは地味に個人的に何処でも使いたいので、地味に登録してみることにした。
<dependency> <groupId>com.github.nodamushi</groupId> <artifactId>common.paths</artifactId> <version>1.0.0</version> </dependency>
初めてやってみたが、ぶっちゃけ、置けないだろって思ってたら、置けてしまった。びっくりだ。
repositoriesを書かなくても、dependencyだけで、ネットから自分のライブラリが勝手にダウンロードされるというのは、妙な気分だね。
参考にしたページ:
- Maven Central Repositoryでパッケージを公開する | エンジニアっぽいことを書くブログ
- GitHub で公開したソースコードを Maven Central Repository に登録する手順 | Tagbangers Blog
GPGはMSYS2ので普通にいけた。
後の祭り
私は普段、ライブラリ系のプロジェクトのartifactIdはgroupIdとくっつけると基準パッケージになるようにつけてます。パッケージ名がhoge.moge.piyoで、groupIdがhogeなら、artifactIdはmoge.piyoって感じ。一律に付けられるからこの命名は楽
なんだけど、よくよく考えたら一般的にはhamcrest-allとかみたいになってるんだよね。
後で気がついたぜ。
まぁ、もうやっちゃったモンは仕方がない。気にしないぜ。(´・∀・`)
地味に便利な関数達
地味に便利な関数を簡単に紹介していこう。
newBufferedReader
地味によく使う。Files.newBufferedReaderと違って、UTF-8のBOMを自動的に無視するBufferedReaderを作成する。ついでにUTF-16にも対応した。
try(var r = NPaths.newBufferedReader(utfFile, StandardCharset.UTF_8){ var line = r.readLine(); //自動的にBOMは無視される }
replaceExtension
地味に割と使う。Pathのファイル名から拡張子だけ変更するときって稀によくある。
var txt = Paths.get("/hoge/piyo.txt"); var csv = NPaths.replaceExtension(txt,"csv"); // /hoge/piyo.csv var ext = NPaths.getExtension(txt); //拡張子取得もあるよ。
ファイル名の先頭に文字追加したり、っていうのもあるよ。
getParent
地味に意識して使う。Pathの親を取得する時に、決してnullを返さない。
面倒くさがってpath.getParent()ってやってて、findBugもせずにヌルポが発生した時の悲しさよ。
var path = Paths.get("a.txt"); var nullpath = path.getParent();//null var nonnull = NPaths.getParent(path); // empty path // parentがnullでも大丈夫なresolve resolve(nullpath"b.txt"); // b.txt
walkFiles
極稀に使う。FileVistorのvisitFileだけを実装することで動かす。潜るディレクトリの深さも指定可能。
とりあえずディレクトリを再帰的にファイルを集めたいとか、再帰的にファイルだけ何か処理したい時に便利。
List<Path> list = new ArrayList<>(); NPaths.walkFiles( dir, -1 ,(path,attr)->{ list.add(path); return FileVisitResult.CONTINUE; });
iterator
あんま使わないかな。
デフォルトのPathのイテレータとの違いは、ルートも一つの要素と見なす。デフォルトのイテレータの様に名前だけにすることも可能。
for(Path p :NPaths.iterator( Paths.get("C:/a/b/c") ){ // p: // 1回目: C:/ // 2回目: C:/a // 3回目: C:/a/b // 4回目: C:/a/b/c }
まとめ
もっと小っちゃいモジュールで世の中が溢れると、良いですね。
といいつつ、結局面倒くさくなって大きな奴を使うんじゃないんかな。