プログラムdeタマゴ

nodamushiの著作物は、文章、画像、プログラムにかかわらず全てUnlicenseです

nio.Pathの小さなユーティリティライブラリを公開してみた

 Google guava………便利だよね。Appache Common………便利だよね。

f:id:nodamushi:20180506204944p:plain

 ………まぁ、デカいとは言わないけど、ちりも積もればなんとやらだよね?


f:id:nodamushi:20180506204654p:plain

 ………でかすぎね?

 そう、私は言いたいのだ。世の便利な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だけで、ネットから自分のライブラリが勝手にダウンロードされるというのは、妙な気分だね。

 参考にしたページ:

 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
}

 

まとめ

 もっと小っちゃいモジュールで世の中が溢れると、良いですね。
 といいつつ、結局面倒くさくなって大きな奴を使うんじゃないんかな。