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 File và Path
- File → Path: file.toPath()
- Path → File: 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 Path và Files.
- Để 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
Path và Files 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.get và resolve.
Chuyển đổi giữa File và Path
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.
GO TO FULL VERSION