エラーの内容
java.io.FileNotFoundException: /path/to/your/file.txt (No such file or directory)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
at java.base/java.io.FileReader.<init>(FileReader.java:75)
at com.example.MyApp.readFile(MyApp.java:12)
Java はファイルを開けない場合にこのエラーをスローします — パスが実際のファイルを指していないか、プロセスに読み取り権限がない場合です。スタックトレースにはエラーが発生した正確な行が示されているので、そこから調査を始めましょう。
原因
- ファイルパスが間違っている — タイポ、間違ったセパレータ、または自分のマシンでしか動作しないハードコードされた絶対パス。
- パスが相対パスだが、JVMの作業ディレクトリが想定した場所にない。
- ファイルが
src/main/resourcesの中にあるのに、クラスパスリソースではなく通常のファイルシステムのファイルとして読み込もうとしている。 - ファイルは存在するが、プロセスに読み取り権限がない。
- Windows で、ハードコードされたパスにスラッシュとバックスラッシュが混在している。
手順別の修正方法
ステップ1 — 実際に解決されたパスを出力する
ここから始めましょう。Java が実際に開こうとしている絶対パスを出力します。この一行で約80%のケースが解決します:
File file = new File("config/settings.txt");
System.out.println("絶対パス: " + file.getAbsolutePath());
System.out.println("存在: " + file.exists());
出力内容を確認しましょう。十中八九、解決されたパスは期待したものとは全く異なります — それが分かれば修正は明らかになります。
ステップ2 — 作業ディレクトリを確認する
相対パスはJVMの作業ディレクトリから解決されます。これはプロセスの起動時に設定されます — ソースファイルの場所ではありません。
System.out.println("作業ディレクトリ: " + System.getProperty("user.dir"));
IntelliJ や Eclipse で開いた Maven/Gradle プロジェクトの場合、通常はプロジェクトルートになります。パッケージ化された JAR の場合、java -jar app.jar と入力したときのディレクトリになります。この2つの環境では、全く異なる場所に解決されることがよくあります。
ステップ3 — 正しいパスを使用する
ファイルがディスク上にある場合(JAR にバンドルされていない場合)、以下の3つのアプローチから選択してください:
// オプションA: 絶対パス — 曖昧さなし
File file = new File("/home/ubuntu/app/config/settings.txt");
// オプションB: 作業ディレクトリからの相対パス(先にステップ2で確認すること)
File file = new File("config/settings.txt");
// オプションC: 環境変数からパスを構築
String basePath = System.getenv("APP_HOME");
File file = new File(basePath + "/config/settings.txt");
クロスプラットフォームのコードでは、文字列連結の代わりに NIO の Paths.get() を複数の引数で使用してください — OS固有のセパレータを自動的に処理します:
Path path = Paths.get("config", "settings.txt");
System.out.println(path.toAbsolutePath());
ステップ4 — クラスパスリソースを読み込む(resourcesフォルダ)
src/main/resources 内のファイルは JAR にバンドルされます。パッケージ化されると、new File() ではアクセスできません。getResourceAsStream() に切り替えましょう:
// 誤り — JAR から実行するときに動作しない
File file = new File("src/main/resources/config.properties");
// 正しい — IDE とパッケージ化された JAR の両方で動作する
try (InputStream is = MyApp.class.getResourceAsStream("/config.properties")) {
if (is == null) {
throw new RuntimeException("リソースが見つかりません: /config.properties");
}
Properties props = new Properties();
props.load(is);
}
先頭の / は重要です。クラスパスルートからの絶対パスになります。これを省略すると、Java はクラスのパッケージからの相対パスとして検索します — おそらくそれは望む動作ではありません。
ステップ5 — ファイルのパーミッションを確認する
ファイルが存在し、パスも正しいのに JVM がファイルを開けない場合があります。通常、プロセスが誤ったユーザーで実行されているか、パーミッションが厳しすぎることを意味します:
# Linux / macOS
ls -la /path/to/your/file.txt
chmod 644 /path/to/your/file.txt
# JVMを実行しているユーザーを確認
ps aux | grep java
Linux では、ファイルは root だけでなく Java プロセスを所有するユーザーが読み取れる必要があります。Windows では、Excel や開いたままのテキストエディタなど、別のアプリケーションによってファイルがロックされていないか確認してください。
ステップ6 — 必要に応じてファイルまたはディレクトリを作成する
新しいファイルに書き込む場合は、先に親ディレクトリが存在することを確認してください。FileWriter は自動的に作成しません:
File file = new File("/var/app/output/report.txt");
// 親ディレクトリが存在しない場合は作成
file.getParentFile().mkdirs();
// これで安全に作成/書き込みができる
try (FileWriter writer = new FileWriter(file)) {
writer.write("hello");
}
修正の確認
アプリ全体を実行する前に、以下の確認コードを追加してください:
File file = new File("your/path/here");
if (!file.exists()) {
System.err.println("ファイルが見つかりません: " + file.getAbsolutePath());
} else if (!file.canRead()) {
System.err.println("読み取り権限がありません: " + file.getAbsolutePath());
} else {
System.out.println("OK: " + file.getAbsolutePath());
}
OK: 以外が出力された場合、修正は完全ではありません。エラーが断続的に発生する場合はこのステップをスキップしないでください — ファイルの存在は環境によって異なる場合があります。
クイックリファレンス
- ディスク上のファイル、間違ったパス →
getAbsolutePath()を出力してパス文字列を修正する。 - resourcesフォルダ内のファイル →
new File()ではなくgetResourceAsStream()を使用する。 - 相対パスの解決が誤っている →
user.dirを出力して、相対パスを調整するか絶対パスに切り替える。 - パーミッション拒否の場合 → Linux では
chmod 644、Windows ではファイルロックを確認する。 - 親ディレクトリが存在しない → 書き込み前に
file.getParentFile().mkdirs()を呼び出す。

