Path / Paths をざっくり一言でいうと
Path は、
「ファイルやディレクトリまでの“道順(パス)”を表すオブジェクト」です。
Paths は、
「Path を作るための “工場(ファクトリ)クラス”」
です。
昔の File と違って、Path は
- OS に依存しない形でパスを扱える
- パス同士の結合・分解・正規化(../ を消すなど)がやりやすい
Filesクラスと組み合わせて、読み書き・コピー・削除など何でもできる
といった modern な API になっています。
Path の基本イメージと作り方
Path は「場所だけ」を表す(中身は読まない)
まず一番大事なのは、Path 自体は
「場所(パス)」を表すだけで、ファイルの中身は扱わないということです。
import java.nio.file.Path;
public class PathBasic {
public static void main(String[] args) {
Path p = Path.of("data/example.txt"); // Java 11 以降
System.out.println(p); // data/example.txt
}
}
Javaこの時点では、
「data/example.txt というパスを指しています」と宣言しただけで、
ファイルが存在するかどうか、開いているかどうかは一切関係ありません。
実際の読み書きは、あとで Files やストリームと組み合わせて行います。
Path の作り方(Path.of と Paths.get)
よく使う作り方は 2 パターンです。
import java.nio.file.Path;
import java.nio.file.Paths;
public class CreatePath {
public static void main(String[] args) {
// Java 11 以降推奨
Path p1 = Path.of("logs/app.log");
// 古くからある方法(Java 7+)
Path p2 = Paths.get("logs", "app.log"); // パス要素を分けて渡す
System.out.println(p1);
System.out.println(p2);
}
}
JavaPaths.get は「可変長引数」なので、
Paths.get("logs/app.log")Paths.get("logs", "2025", "01", "app.log")
のように、「フォルダごとに区切って渡す」こともできます。
OS によって区切り文字(/ や \)が違っても、Paths.get がうまく吸収してくれます。
絶対パス・相対パス・正規化(../ をきれいにする)
絶対パスと相対パス
Path は、相対パスでも絶対パスでも表せます。
Path relative = Path.of("logs/app.log"); // カレントディレクトリからの相対パス
Path absolute = relative.toAbsolutePath(); // 絶対パスに変換
System.out.println("相対: " + relative);
System.out.println("絶対: " + absolute);
JavatoAbsolutePath() を使うと、
「実際にはどの場所を指しているのか」がはっきり見えるので、
デバッグ時にかなり役立ちます。
.. や . をきれいに消す normalize
パスの中に . や .. が含まれていても、normalize() でスッキリさせられます。
Path p = Path.of("logs/../logs/./2025/app.log");
System.out.println("そのまま: " + p); // logs/../logs/./2025/app.log
Path normalized = p.normalize();
System.out.println("正規化後: " + normalized); // logs/2025/app.log
Javanormalize() は、
.(カレント)を消すx/..のような、「一度下って戻る」部分をいい感じに畳む
ことで、「最短のパス表現」にしてくれます。
Path 同士の結合・相対パス計算(resolve / relativize)
resolve でパスをつなげる
resolve は、
「親パスに子のパス要素をつなげる」メソッドです。
import java.nio.file.Path;
public class ResolveExample {
public static void main(String[] args) {
Path base = Path.of("logs");
Path child = Path.of("2025/app.log");
Path combined = base.resolve(child);
System.out.println(combined); // logs/2025/app.log
}
}
Java文字列の足し算("logs/" + "2025/app.log")でやるよりも安全で、
OS による区切り文字の違いも気にしなくてよくなります。
relativize で「ベースからの相対パス」を求める
relativize は、
「あるパスから見て、別のパスまでの相対パス」を計算します。
import java.nio.file.Path;
public class RelativizeExample {
public static void main(String[] args) {
Path base = Path.of("logs");
Path target = Path.of("logs/2025/01/app.log");
Path relative = base.relativize(target);
System.out.println(relative); // 2025/01/app.log
Path back = target.relativize(base);
System.out.println(back); // ../..
}
}
Javalogsからlogs/2025/01/app.logを見ると2025/01/app.log- 逆方向だと
../..
というように、相対移動のパスが手に入ります。
Path と Files の組み合わせでファイル操作を行う
Files.exists / isRegularFile / isDirectory
Path は「住所」なので、
実際の存在チェックや属性チェックは Files クラスで行います。
import java.nio.file.*;
public class FilesCheck {
public static void main(String[] args) throws Exception {
Path p = Path.of("data.txt");
System.out.println("存在する? : " + Files.exists(p));
System.out.println("通常のファイル? : " + Files.isRegularFile(p));
System.out.println("ディレクトリ? : " + Files.isDirectory(p));
}
}
Javajava.io.File の exists()/isFile()/isDirectory() と似ていますが、Files + Path の方が新しく、より強力です。
1 行で読み書き:readString / writeString
Path があれば、ファイルの読み書きはかなりシンプルに書けます。
import java.nio.file.*;
public class FilesReadWrite {
public static void main(String[] args) throws Exception {
Path path = Path.of("sample.txt");
// 書き込み(上書き)
Files.writeString(path, "Hello\nWorld\n");
// 読み込み
String content = Files.readString(path);
System.out.println(content);
}
}
Javaテキストファイルを扱う「最短ルート」はほぼこれです。Path は単なる場所、実際の I/O は Files が担当する、という役割分担になっています。
File と Path の違い・相互変換(ここをしっかり理解する)
なぜ今は Path を使うべきと言われるのか
古い java.io.File と比べて、Path / Files にはこんな利点があります。
- 例外ベースでエラーが分かりやすい(File は true/false だけで曖昧になりがち)
- パス操作(結合・正規化・相対化)が高機能で直感的
- シンボリックリンク・属性情報など、より多くの情報にアクセスしやすい
- ファイル監視や大規模ファイル操作にも向いた modern API
なので、新しく書くコードでは基本 Path / Files を使うのが推奨されています。
File ↔ Path の相互変換
とはいえ、既存ライブラリは File を受け取ることが多いので、
相互変換のやり方も覚えておきましょう。
import java.io.File;
import java.nio.file.Path;
public class FilePathConvert {
public static void main(String[] args) {
// File → Path
File file = new File("data.txt");
Path pathFromFile = file.toPath();
// Path → File
Path path = Path.of("data.txt");
File fileFromPath = path.toFile();
System.out.println(pathFromFile);
System.out.println(fileFromPath.getAbsolutePath());
}
}
JavaFile#toPath() と Path#toFile() がセットになっています。
まとめ:Path / Paths を自分の中でこう位置づける
Path / Paths を初心者向けに整理すると、こうなります。
Pathは、ファイルやディレクトリまでの「道順」を表すインターフェースPaths(とPath.of)は、そのPathを作るための“工場”Path自体は中身を読まない。存在チェックや読み書きはFilesと組み合わせて行う- パスの結合(
resolve)、相対パス計算(relativize)、正規化(normalize)が強力 Fileより新しく、modern なファイル操作の標準 API なので、新規コードでは基本こっち
