LoginSignup
2
3

More than 5 years have passed since last update.

参考メモ/Java7のnio2のファイル操作の便利機能(basename,dirname,realpath相当とファイルの簡易読み書き)

Last updated at Posted at 2016-04-09

Java7で導入されたNIO.2のファイルI/Oでいろいろ便利になったので、前から気になってた「Javaで他の言語であるbasename,dirname,realpath相当はどうするの?」や、「ファイル内容の一気読み/一気書き、もうちょっと簡単に書けないかな?」というのを試したメモです。

NIO.2の新しいファイル操作については、公式チュートリアルの以下が非常によくまとめてくれてました。この記事で紹介してる以外の機能など、いろいろ「え、こんなのも出来るように!?」というのがあるので、一度ざっと見てみると面白いです。

※Java7からの機能の解説記事ではありますが、サンプルコードは記事執筆時点でのメジャーバージョンであるJava8で行ってます。参考URLなどもJava8のものを載せてますので、ご了承ください。

掲載サンプルコードのコンパイル&実行確認環境:
$ java -version
java version "1.8.0_77"
Java(TM) SE Runtime Environment (build 1.8.0_77-b03)
Java HotSpot(TM) 64-Bit Server VM (build 25.77-b03, mixed mode)

なお、本記事では basename,dirname,realpath についてPHP関数の動きをイメージしてます。ですので、PHPプログラマがJavaを使うときに「あれ、PHPでのbasename/dirname/realpathはJavaだとどう書くんだっけ?」という時に本記事はぴったりかもです。

basename,dirname相当

最初の紹介で申し訳ないですが、これについてはJava6以前の java.io.File クラスでも提供されてたようで・・・自分が知らないだけだったようです(汗)。

FileNames.java
import java.io.*;
import java.nio.file.*;

public class FileNames {
    public static void main(String[] args) throws Exception {
        String fname = args[0];

        File oldf = new File(fname);
        System.out.println("File.separator=" + File.separator);
        System.out.println("File.pathSeparator=" + File.pathSeparator);
        System.out.println("File.getAbsolutePath()=" + oldf.getAbsolutePath());
        System.out.println("File.getCanonicalPath()=" + oldf.getCanonicalPath());
        System.out.println("File.getName()=" + oldf.getName());
        System.out.println("File.getParent()=" + oldf.getParent());
        System.out.println("File.getPath()=" + oldf.getPath());

        Path newp = Paths.get(fname);
        System.out.println("Path.getFileName()=" + newp.getFileName().toString());
        System.out.println("Path.getParent()=" + newp.getParent().toString());
        if (newp.getRoot() != null) {
            System.out.println("Path.getRoot()=" + newp.getRoot().toString());
        }
        System.out.println("Path.normalize()=" + newp.normalize().toString());
        System.out.println("Path.toAbsolutePath()=" + newp.toAbsolutePath().toString());
        System.out.println("Path.toRealPath()=" + newp.toRealPath().toString());
    }
}

例:

$ java FileNames ../../java/hoge.java 
File.separator=/
File.pathSeparator=:
File.getAbsolutePath()=/home/msakamoto/work/java/nio2-fileio/../../java/hoge.java
File.getCanonicalPath()=/home/msakamoto/work/java/hoge.java
File.getName()=hoge.java
File.getParent()=../../java
File.getPath()=../../java/hoge.java
Path.getFileName()=hoge.java
Path.getParent()=../../java
Path.normalize()=../../java/hoge.java
Path.toAbsolutePath()=/home/msakamoto/work/java/nio2-fileio/../../java/hoge.java
Path.toRealPath()=/home/msakamoto/work/java/hoge.java

basename,dirname,realpath相当

大体のマッピングです。

  • basename相当(ファイルパスの内、ファイル名だけを抜き出す)
    • File.getName() : String
    • Path.getFileName() : Pathオブジェクト
  • dirname相当(ファイルパスの内、ファイルの所属するディレクトリ名を抜き出す)
    • File.getParent() : String
    • Path.getParent() : Pathオブジェクト
  • realpath相当(相対パスを絶対パスに変換)
    • Path.toRealPath() : Pathオブジェクト

参考

Java8 API :

その他:

ファイル読み書きのショートカット

Filesクラスに便利なのが用意されました。

  • https://docs.oracle.com/javase/jp/8/docs/api/java/nio/file/Files.html

  • 全バイトを一気読み

    • Files.readAllBytes(Path path)
  • テキストを一行ずつ一気読み(次のコードポイントを改行として認識 : \u000D + \u000A = CRLF, \u000A = LF, \u000D = CR)

    • Files.readAllLines(Path path)
    • Files.readAllLines(Path path, Charset cs)
  • 全バイトを一気書き

    • Files.write(Path path, byte[] bytes, OpenOption... options)
  • 文字列のリストを一行ずつ一気書き(改行コードは line.separator システムプロパティ)

    • Files.write(Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption... options)
    • Files.write(Path path, Iterable<? extends CharSequence> lines, OpenOption... options)

一行ずつ一気読みのサンプルコード:

ReadLines.java
import java.nio.charset.*;
import java.nio.file.*;

public class ReadLines {
    public static void main(String[] args) throws Exception {
        for (String line : Files.readAllLines(Paths.get(args[0]), Charset.forName(args[1]))) {
            System.out.println(line);
        }
    }
}

試しにCR, CRLF, LF で改行したテキストファイルを読み込ませたところ、混在しててもちゃんと一行ずつに分割してくれました。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3