Sửa lỗi java.io.FileNotFoundException: No such file or directory trong Java

beginner Java2026-03-18| Java 8+, mọi hệ điều hành (Linux, macOS, Windows), dự án Maven/Gradle, Spring Boot

Error Message

java.io.FileNotFoundException: /path/to/your/file.txt (No such file or directory)
#java#io#file#exception#FileNotFoundException

Lỗi gì xảy ra

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 ném lỗi này khi không thể mở một file — hoặc vì đường dẫn không trỏ đến thứ gì thực sự tồn tại, hoặc vì tiến trình không có quyền đọc. Stack trace cho biết chính xác dòng code nào gây ra lỗi, vì vậy hãy bắt đầu từ đó.

Nguyên nhân gốc rễ

  • Đường dẫn file bị sai — lỗi đánh máy, dấu phân cách sai, hoặc đường dẫn tuyệt đối hardcode chỉ hoạt động trên máy của bạn.
  • Đường dẫn là tương đối, nhưng working directory của JVM không phải nơi bạn nghĩ.
  • File nằm trong src/main/resources và bạn đang đọc nó như một file hệ thống thông thường thay vì classpath resource.
  • File tồn tại nhưng tiến trình không có quyền đọc.
  • Trên Windows, trộn lẫn dấu gạch chéo xuôi và ngược trong đường dẫn hardcode.

Cách sửa từng bước

Bước 1 — In đường dẫn thực tế đã được resolve

Bắt đầu từ đây. In đường dẫn tuyệt đối mà Java đang thực sự cố mở. Một dòng này giải quyết khoảng 80% trường hợp:

File file = new File("config/settings.txt");
System.out.println("Đường dẫn tuyệt đối: " + file.getAbsolutePath());
System.out.println("Tồn tại: " + file.exists());

Xem kết quả in ra. Chín phần mười, đường dẫn được resolve trông không giống những gì bạn mong đợi — và khi nhìn thấy nó, cách sửa trở nên rõ ràng.

Bước 2 — Kiểm tra working directory

Đường dẫn tương đối được resolve từ working directory của JVM. Nó được thiết lập khi tiến trình khởi động — không phải nơi file source code tồn tại.

System.out.println("Thư mục làm việc: " + System.getProperty("user.dir"));

Với các dự án Maven/Gradle mở trong IntelliJ hoặc Eclipse, đây thường là thư mục gốc của project. Với JAR đã đóng gói, đó là thư mục bạn đang đứng khi gõ java -jar app.jar. Hai môi trường này thường resolve đến những nơi hoàn toàn khác nhau.

Bước 3 — Dùng đường dẫn đúng

Khi file nằm trên đĩa (không được đóng gói trong JAR), hãy chọn một trong ba cách sau:

// Option A: đường dẫn tuyệt đối — không nhập nhằng
File file = new File("/home/ubuntu/app/config/settings.txt");

// Option B: tương đối so với working directory (kiểm tra bước 2 trước)
File file = new File("config/settings.txt");

// Option C: xây dựng đường dẫn từ biến môi trường
String basePath = System.getenv("APP_HOME");
File file = new File(basePath + "/config/settings.txt");

Với code đa nền tảng, dùng Paths.get() của NIO với nhiều tham số thay vì nối chuỗi — nó tự động xử lý dấu phân cách theo từng hệ điều hành:

Path path = Paths.get("config", "settings.txt");
System.out.println(path.toAbsolutePath());

Bước 4 — Đọc classpath resource (thư mục resources)

Các file trong src/main/resources được đóng gói vào JAR. Sau khi đóng gói, new File() không thể truy cập chúng. Hãy chuyển sang dùng getResourceAsStream():

// SAI — lỗi khi chạy từ JAR
File file = new File("src/main/resources/config.properties");

// ĐÚNG — hoạt động trong cả IDE và JAR đóng gói
try (InputStream is = MyApp.class.getResourceAsStream("/config.properties")) {
    if (is == null) {
        throw new RuntimeException("Không tìm thấy resource: /config.properties");
    }
    Properties props = new Properties();
    props.load(is);
}

Dấu / ở đầu rất quan trọng. Nó làm cho đường dẫn là tuyệt đối từ gốc classpath. Bỏ đi, Java sẽ tìm tương đối so với package của class — có thể không phải điều bạn muốn.

Bước 5 — Kiểm tra quyền truy cập file

Đôi khi file tồn tại và đường dẫn đúng, nhưng JVM vẫn không thể mở. Thường là do tiến trình đang chạy với user sai, hoặc quyền truy cập quá hạn chế:

# Linux / macOS
ls -la /path/to/your/file.txt
chmod 644 /path/to/your/file.txt

# Kiểm tra user nào đang chạy JVM
ps aux | grep java

Trên Linux, file cần có quyền đọc cho user đang sở hữu tiến trình Java — không chỉ root. Trên Windows, kiểm tra xem file có bị khóa bởi ứng dụng khác như Excel hay text editor đang mở không.

Bước 6 — Tạo file hoặc thư mục nếu cần

Ghi vào file mới? Hãy đảm bảo thư mục cha tồn tại trước. FileWriter sẽ không tự tạo chúng:

File file = new File("/var/app/output/report.txt");

// Tạo thư mục cha nếu chưa tồn tại
file.getParentFile().mkdirs();

// Giờ đã an toàn để tạo/ghi
try (FileWriter writer = new FileWriter(file)) {
    writer.write("hello");
}

Kiểm tra sau khi sửa

Trước khi chạy toàn bộ ứng dụng, thêm đoạn kiểm tra này vào code:

File file = new File("your/path/here");
if (!file.exists()) {
    System.err.println("Không tìm thấy file: " + file.getAbsolutePath());
} else if (!file.canRead()) {
    System.err.println("Không có quyền đọc: " + file.getAbsolutePath());
} else {
    System.out.println("OK: " + file.getAbsolutePath());
}

Nếu có gì khác ngoài OK: được in ra, nghĩa là chưa sửa xong. Đừng bỏ qua bước này khi lỗi xảy ra không ổn định — sự tồn tại của file có thể khác nhau giữa các môi trường.

Tóm tắt nhanh

  • File trên đĩa, đường dẫn sai → in getAbsolutePath(), sửa chuỗi đường dẫn.
  • File trong thư mục resources → dùng getResourceAsStream(), không dùng new File().
  • Đường dẫn tương đối resolve sai → in user.dir, điều chỉnh đường dẫn tương đối hoặc chuyển sang tuyệt đối.
  • Lỗi dạng Permission deniedchmod 644 trên Linux, hoặc kiểm tra file lock trên Windows.
  • Thư mục cha chưa tồn tại → gọi file.getParentFile().mkdirs() trước khi ghi.

Related Error Notes