CodeGym /Các khóa học /JAVA 25 SELF /Các lớp File, Path, Files: tổng quan, tạo đối tượng

Các lớp File, Path, Files: tổng quan, tạo đối tượng

JAVA 25 SELF
Mức độ , Bài học
Có sẵn

1. Lớp File: khởi đầu như thế nào

Mặc dù chúng ta đã kết luận rằng lớp File không nên dùng trong các dự án mới, vẫn có rất nhiều hệ thống legacy nơi nó được sử dụng. Vì vậy, cần hiểu và biết cách làm việc với nó. Lớp File là cách cũ để biểu diễn tệp hoặc thư mục trên đĩa. Nhưng đừng nhầm lẫn: đối tượng File không phải là tệp thực, mà chỉ là “con trỏ”/“hộ chiếu” của đường dẫn. Ví dụ, biểu thức File f = new File("hello.txt"); không tạo tệp trên đĩa — bạn chỉ mô tả đường dẫn.

Tạo một đối tượng File như thế nào?

import java.io.File;

public class FileDemo {
    public static void main(String[] args) {
        File file = new File("example.txt"); // đường dẫn tương đối
        File folder = new File("mydir");     // thư mục

        System.out.println("Đường dẫn tuyệt đối: " + file.getAbsolutePath());
        System.out.println("Tệp có tồn tại không? " + file.exists());
        System.out.println("Đây có phải là tệp? " + file.isFile());
        System.out.println("Đây có phải là thư mục? " + folder.isDirectory());
    }
}

Điều quan trọng cần nhớ:
Tạo đối tượng File không tạo tệp trên đĩa. Nó chỉ là “lối tắt”. Để tệp thực sự xuất hiện, cần chủ động tạo (ví dụ, ghi dữ liệu hoặc gọi file.createNewFile()).

Các phương thức chính của lớp File

  • exists() — kiểm tra tệp/thư mục có tồn tại hay không.
  • isFile() — đây có phải là tệp (không phải thư mục) không?
  • isDirectory() — đây có phải là thư mục không?
  • getAbsolutePath() — lấy đường dẫn tuyệt đối.
  • length() — kích thước tệp theo byte.
  • getName() — tên tệp hoặc thư mục.
  • delete() — xóa tệp/thư mục (nếu trống).

Ví dụ: in thông tin về tệp

File file = new File("example.txt");
System.out.println("Tên: " + file.getName());
System.out.println("Đường dẫn: " + file.getAbsolutePath());
System.out.println("Kích thước: " + file.length() + " byte");
System.out.println("Tồn tại? " + file.exists());

2. Lớp Path: cách tiếp cận hiện đại đối với tệp

Path là một phần của file API mới (NIO.2, từ Java 7). Đây là trừu tượng của đường dẫn đến tệp/thư mục; đường dẫn có thể không chỉ ở đĩa cục bộ mà còn, ví dụ, bên trong tệp ZIP hoặc trên tài nguyên từ xa (nếu có provider tương ứng).

Nếu File là bản đồ giấy cũ, thì Path là máy định vị GPS.

Cách tạo đối tượng Path?

import java.nio.file.Path;
import java.nio.file.Paths;

public class PathDemo {
    public static void main(String[] args) {
        Path path1 = Paths.get("example.txt"); // đường dẫn tương đối
        Path path2 = Paths.get("folder", "file.txt"); // ghép các phần đường dẫn

        System.out.println("Đường dẫn 1: " + path1.toAbsolutePath());
        System.out.println("Đường dẫn 2: " + path2.toAbsolutePath());
    }
}

Ưu điểm: không cần bận tâm về dấu phân cách. Paths.get sẽ chọn định dạng phù hợp với hệ điều hành của bạn.

Chuyển đổi giữa FilePath

  • FilePath: file.toPath()
  • PathFile: path.toFile()
File file = new File("test.txt");
Path path = file.toPath();

Path anotherPath = Paths.get("data.txt");
File anotherFile = anotherPath.toFile();

Làm việc với đường dẫn: resolve, relativize, normalize

Ghép đường dẫn (resolve)

Path dir = Paths.get("myfolder");
Path file = dir.resolve("notes.txt"); // myfolder/notes.txt
System.out.println(file); // myfolder/notes.txt

Đường dẫn tương đối (relativize)

Path pathA = Paths.get("folderA/file1.txt");
Path pathB = Paths.get("folderA/subfolder/file2.txt");
Path relative = pathA.relativize(pathB);
System.out.println(relative); // ../subfolder/file2.txt

Chuẩn hóa đường dẫn (normalize)

Path messy = Paths.get("folder/../folder/file.txt");
Path clean = messy.normalize();
System.out.println(clean); // folder/file.txt

Ví dụ: xây dựng đường dẫn đến tệp

Path home = Paths.get(System.getProperty("user.home"));
Path docs = home.resolve("Documents");
Path myFile = docs.resolve("myfile.txt");
System.out.println("Đường dẫn tới tệp: " + myFile.toAbsolutePath());

3. Lớp Files: “dao đa năng” của bạn

Lớp Files trong gói java.nio.file là tập hợp phương thức tĩnh tiện ích để làm việc với tệp và thư mục dựa trên Path. Nó gần như làm được tất cả: kiểm tra tồn tại, tạo/xóa, đọc/ghi, sao chép/di chuyển, lấy thuộc tính và duyệt cây thư mục.

Các phương thức chính của lớp Files

  • Files.exists(path) — kiểm tra tệp/thư mục có tồn tại hay không.
  • Files.isDirectory(path) — đây có phải là thư mục không?
  • Files.size(path) — kích thước tệp.
  • Files.createFile(path) — tạo tệp.
  • Files.createDirectory(path) — tạo thư mục.
  • Files.delete(path) — xóa tệp/thư mục.
  • Files.copy(src, dest) — sao chép tệp.
  • Files.move(src, dest) — di chuyển/đổi tên.
  • Files.getLastModifiedTime(path) — thời điểm sửa đổi cuối cùng.
  • Files.readAllBytes(path) — đọc toàn bộ tệp vào mảng byte.
  • Files.readAllLines(path) — đọc mọi dòng của tệp văn bản.
  • Files.write(path, bytes) — ghi byte vào tệp.

Ví dụ: kiểm tra tệp

import java.nio.file.*;

public class FilesDemo {
    public static void main(String[] args) {
        Path path = Paths.get("example.txt");

        System.out.println("Tệp có tồn tại không? " + Files.exists(path));
        System.out.println("Đây có phải là thư mục? " + Files.isDirectory(path));

        if (Files.exists(path)) {
            try {
                System.out.println("Kích thước tệp: " + Files.size(path) + " byte");
            } catch (Exception e) {
                System.out.println("Lỗi khi lấy kích thước: " + e.getMessage());
            }
        }
    }
}

4. Thực hành: tạo đối tượng, in thuộc tính

Tạo đối tượng cho tệp và thư mục

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;

public class CompareDemo {
    public static void main(String[] args) {
        // Cách cũ
        File oldFile = new File("test.txt");
        File oldDir = new File("mydir");

        // Cách mới
        Path newFile = Paths.get("test.txt");
        Path newDir = Paths.get("mydir");

        System.out.println("=== File API ===");
        System.out.println("Tệp: " + oldFile.getAbsolutePath());
        System.out.println("Tồn tại? " + oldFile.exists());
        System.out.println("Đây có phải là tệp? " + oldFile.isFile());
        System.out.println("Đây có phải là thư mục? " + oldDir.isDirectory());

        System.out.println("\n=== Path API ===");
        System.out.println("Tệp: " + newFile.toAbsolutePath());
        System.out.println("Tồn tại? " + java.nio.file.Files.exists(newFile));
        System.out.println("Đây có phải là tệp? " + java.nio.file.Files.isRegularFile(newFile));
        System.out.println("Đây có phải là thư mục? " + java.nio.file.Files.isDirectory(newDir));
    }
}

In thuộc tính của tệp

import java.nio.file.*;

public class FileProperties {
    public static void main(String[] args) {
        Path path = Paths.get("test.txt");

        System.out.println("Đường dẫn tuyệt đối: " + path.toAbsolutePath());
        System.out.println("Tên tệp: " + path.getFileName());
        System.out.println("Thư mục cha: " + path.getParent());

        if (Files.exists(path)) {
            try {
                System.out.println("Kích thước: " + Files.size(path) + " byte");
                System.out.println("Chỉnh sửa lần cuối: " + Files.getLastModifiedTime(path));
            } catch (Exception e) {
                System.out.println("Lỗi khi lấy thông tin: " + e.getMessage());
            }
        } else {
            System.out.println("Không tìm thấy tệp.");
        }
    }
}

5. So sánh: File vs Path/Files

Khả năng File (java.io) Path + Files (java.nio.file)
Biểu diễn đường dẫn Chỉ đĩa cục bộ Đĩa cục bộ, ZIP, tài nguyên mạng
Ghép đường dẫn Ghép thủ công bằng dấu gạch chéo Thuận tiện qua resolve
Kiểm tra sự tồn tại exists() Files.exists(path)
Đọc/ghi nội dung Không Có (Files.readAll..., Files.write)
Lấy thuộc tính Cơ bản (length(), lastModified()) Thuộc tính và biểu diễn mở rộng
Tương thích Với mọi phiên bản Java Java 7 trở lên
Làm việc với symlink Hạn chế Hỗ trợ đầy đủ

Tóm tắt: khi nào dùng cái gì?

  • Với dự án mới — hãy dùng PathFiles.
  • Để bảo trì mã cũ — đôi khi bạn sẽ phải làm việc với File.

6. Những lưu ý hữu ích

Đường dẫn tương đối và tuyệt đối

Đường dẫn tương đối là đường dẫn tính từ thư mục làm việc hiện tại; đường dẫn tuyệt đối là đường dẫn đầy đủ tính từ gốc của hệ thống tệp.

Path relative = Paths.get("data", "file.txt");
Path absolute = relative.toAbsolutePath();
System.out.println("Đường dẫn tuyệt đối: " + absolute);

Đa nền tảng

PathFiles tính đến đặc thù của hệ điều hành (dấu phân cách, mã hóa, v.v.). Đừng viết đường dẫn dạng "C:\\folder\\file.txt" — hãy dùng Paths.getresolve.

Chuyển đổi giữa FilePath

Nếu bạn có mã cũ dùng File, việc chuyển sang API mới rất dễ:

File legacy = new File("legacy.txt");
Path modern = legacy.toPath();
if (Files.exists(modern)) {
    // Bây giờ có thể dùng toàn bộ khả năng của NIO.2
}

Kiểm tra sự tồn tại của tệp

Path path = Paths.get("notes.txt");
if (Files.exists(path)) {
    System.out.println("Đã tìm thấy tệp!");
} else {
    System.out.println("Tệp không tồn tại.");
}

7. Thực hành nhỏ: tạo và kiểm tra tệp và thư mục

import java.nio.file.*;

public class MiniPractice {
    public static void main(String[] args) throws Exception {
        Path dir = Paths.get("demo_dir");
        Path file = dir.resolve("hello.txt");

        // Tạo thư mục nếu chưa tồn tại
        if (!Files.exists(dir)) {
            Files.createDirectory(dir);
            System.out.println("Đã tạo thư mục: " + dir.toAbsolutePath());
        }

        // Tạo tệp nếu chưa tồn tại
        if (!Files.exists(file)) {
            Files.createFile(file);
            System.out.println("Đã tạo tệp: " + file.toAbsolutePath());
        }

        // In thuộc tính
        System.out.println("Tệp có tồn tại không? " + Files.exists(file));
        System.out.println("Đây có phải là tệp? " + Files.isRegularFile(file));
        System.out.println("Kích thước: " + Files.size(file) + " byte");

        // Xóa tệp và thư mục (tùy ý)
        Files.delete(file);
        Files.delete(dir);
        System.out.println("Đã xóa tệp và thư mục.");
    }
}

8. Lỗi thường gặp khi làm việc với File/Path/Files

Lỗi 1: Nhầm lẫn giữa File và Path. Nhiều người mới cố dùng các phương thức Files với đối tượng File. Hãy nhớ: Files.* làm việc với Path. Nếu bạn có File, trước hết hãy gọi file.toPath().

Lỗi 2: Nghĩ rằng tạo đối tượng File hoặc Path sẽ tạo ra tệp. Đối tượng đường dẫn chỉ là lối tắt, không phải tệp thật. Để tạo, hãy dùng Files.createFile(path) hoặc ghi dữ liệu.

Lỗi 3: Ghép đường dẫn thủ công bằng chuỗi. Đừng viết "folder/file.txt" hay "folder\\file.txt". Hãy dùng Paths.get(...) và resolve(...). Cách này an toàn và đa nền tảng.

Lỗi 4: Bỏ qua ngoại lệ. Các thao tác với tệp có thể ném IOException và các ngoại lệ khác. Hãy xử lý qua try-catch hoặc ném lên trên (throws).

Lỗi 5: Kiểm tra bằng File.exists(), rồi lại thao tác bằng Path. Cố gắng nhất quán theo một phong cách: đã bắt đầu với Path — hãy dùng Files.exists(path) và các phương thức khác của Files.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION