CodeGym /Các khóa học /JAVA 25 SELF /Làm việc với thư mục: tạo, xóa, xem nội dung

Làm việc với thư mục: tạo, xóa, xem nội dung

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

1. Tạo thư mục

Thư mục (còn gọi là “folder”) — không chỉ là bộ chứa tệp, mà là nền tảng tổ chức dữ liệu trên đĩa. Trong ứng dụng, chúng ta thường xuyên tạo thư mục cho dữ liệu vào/ra, log, tệp tạm, v.v. API hiện đại java.nio.file giúp việc này thuận tiện và đa nền tảng.

Hãy xem cách tạo, xóa và xem nội dung thư mục bằng các lớp Files, PathPaths.

Files.createDirectory(path)

Tạo một thư mục tại đường dẫn được chỉ định. Nếu thư mục cha không tồn tại — sẽ ném ngoại lệ.

import java.nio.file.*;

public class DirectoryDemo {
    public static void main(String[] args) throws Exception {
        Path dir = Paths.get("testDir");
        if (!Files.exists(dir)) {
            Files.createDirectory(dir);
            System.out.println("Thư mục đã được tạo: " + dir.toAbsolutePath());
        } else {
            System.out.println("Thư mục đã tồn tại: " + dir.toAbsolutePath());
        }
    }
}

Nếu bạn cố tạo thư mục đã tồn tại, bạn sẽ nhận FileAlreadyExistsException.

Files.createDirectories(path)

Tạo toàn bộ chuỗi thư mục. Nếu thiếu bất kỳ thư mục trung gian nào — nó sẽ được tạo tự động. Nếu một phần chuỗi đã tồn tại — sẽ không có lỗi.

Path nestedDir = Paths.get("parent/child/grandchild");
Files.createDirectories(nestedDir);
System.out.println("Đã tạo chuỗi thư mục: " + nestedDir.toAbsolutePath());

Giống như nhờ Java xây không chỉ căn nhà mà cả hành lang và con đường nếu chúng chưa tồn tại.

Ví dụ điển hình: tạo cấu trúc cho dự án

Giả sử cần lưu báo cáo vào thư mục output/reports/2024. Đừng kiểm tra từng thư mục bằng tay — hãy dùng createDirectories.

Path reportsPath = Paths.get("output/reports/2024");
Files.createDirectories(reportsPath);

Java sẽ tự xử lý phần nào đã có và phần nào cần tạo.

2. Xóa tệp và thư mục

Files.delete(path)

Xóa tệp hoặc thư mục rỗng. Nếu thư mục không rỗng — sẽ ném DirectoryNotEmptyException.

Path dir = Paths.get("testDir");
try {
    Files.delete(dir);
    System.out.println("Thư mục đã bị xóa: " + dir.toAbsolutePath());
} catch (DirectoryNotEmptyException e) {
    System.out.println("Không thể xóa: thư mục không rỗng!");
}

Files.deleteIfExists(path)

Hoạt động như delete, nhưng không ném lỗi nếu đối tượng không tồn tại. Trả về true nếu có gì đó đã bị xóa, và false — nếu đối tượng không tồn tại.

Path file = Paths.get("output/reports/2024/report.txt");
if (Files.deleteIfExists(file)) {
    System.out.println("Tệp đã bị xóa.");
} else {
    System.out.println("Không tìm thấy tệp, không có gì bị xóa.");
}

Làm thế nào xóa thư mục không rỗng?

Không thể xóa trực tiếp một thư mục không rỗng. Trước tiên cần xóa toàn bộ nội dung của nó (tệp và thư mục con), sau đó mới xóa chính thư mục. Làm việc này theo cách đệ quy, ví dụ qua Files.walkFileTree:

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public class DeleteDirectoryRecursively {
    public static void main(String[] args) throws IOException {
        Path dir = Paths.get("parent");
        if (Files.exists(dir)) {
            Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    Files.delete(file);
                    return FileVisitResult.CONTINUE;
                }
                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    Files.delete(dir);
                    return FileVisitResult.CONTINUE;
                }
            });
            System.out.println("Thư mục và toàn bộ nội dung của nó đã bị xóa.");
        }
    }
}

Nếu bạn mới bắt đầu, đừng sợ đoạn mã này — sau đó chúng ta sẽ tìm hiểu walkFileTree chi tiết hơn.

3. Xem nội dung thư mục

Files.list(path)

Trả về Stream<Path> — một luồng các đường dẫn. Bạn có thể xử lý nội dung thư mục qua Stream API. Mỗi phần tử là tệp hoặc thư mục con (không đệ quy!).

Path dir = Paths.get("output/reports");
if (Files.exists(dir) && Files.isDirectory(dir)) {
    try (var stream = Files.list(dir)) {
        stream.forEach(path -> System.out.println(path.getFileName()));
    }
}

Chi tiết quan trọng: bắt buộc phải đóng stream, vì vậy hãy dùng try‑with‑resources.

Ví dụ: in tên tệp và thư mục con

Path reports2024 = Paths.get("output/reports/2024");
try (var stream = Files.list(reports2024)) {
    stream.forEach(path -> {
        String type = Files.isDirectory(path) ? "thư mục" : "tệp";
        System.out.println(path.getFileName() + " — " + type);
    });
}

Lấy danh sách tệp dưới dạng collection

List<Path> files = Files.list(reports2024)
    .filter(Files::isRegularFile)
    .toList();

System.out.println("Các tệp trong thư mục:");
files.forEach(System.out::println);

Quan trọng: Files.list(path) chỉ trả về nội dung của thư mục hiện tại (cấp trên cùng). Để duyệt đệ quy hãy dùng Files.walk(path).

4. Thực hành: trình quản lý tệp mini

Tiện ích tạo thư mục mydata/logs, tệp log1.txt, in nội dung thư mục rồi xóa tất cả.

import java.nio.file.*;
import java.io.IOException;

public class MiniFileManager {
    public static void main(String[] args) throws IOException {
        Path logsDir = Paths.get("mydata/logs");
        Files.createDirectories(logsDir);

        Path logFile = logsDir.resolve("log1.txt");
        Files.writeString(logFile, "Xin chào, log!");

        System.out.println("Nội dung của thư mục " + logsDir + ":");
        try (var stream = Files.list(logsDir)) {
            stream.forEach(path -> System.out.println(" - " + path.getFileName()));
        }

        Files.deleteIfExists(logFile);
        Files.deleteIfExists(logsDir);
        System.out.println("Tệp và thư mục đã bị xóa.");
    }
}

Ghi chú cho mã:

  • Files.createDirectories đảm bảo tạo toàn bộ chuỗi thư mục.
  • resolve — cách tiện lợi để thêm tên tệp vào đường dẫn.
  • Đóng stream từ Files.list bằng try‑with‑resources — đặc biệt quan trọng trên Windows.

5. Đặc thù và lưu ý

Kiểm tra sự tồn tại

Trước khi tạo/xóa, nên kiểm tra đường dẫn có tồn tại hay không:

if (!Files.exists(path)) {
    Files.createDirectory(path);
}

Quyền truy cập

Nếu chương trình không có quyền để tạo/xóa — bạn sẽ nhận AccessDeniedException. Ví dụ, tạo thư mục ở thư mục gốc của ổ đĩa bằng tài khoản người dùng thông thường gần như chắc chắn sẽ gặp lỗi.

Thư mục rỗng và không rỗng

Chỉ có thể xóa thư mục rỗng (Files.delete). Để xóa kèm toàn bộ nội dung, hãy dùng duyệt đệ quy (walkFileTree).

Đa nền tảng

API java.nio.file hoạt động đúng trên các HĐH phổ biến và xét đến dấu phân cách đường dẫn. Để xây dựng đường dẫn, hãy dùng Paths.getPath.resolve, thay vì nối chuỗi.

Liên kết tượng trưng

Trong các tác vụ cơ bản có thể chưa cần để ý, nhưng nếu gặp các mục “bất thường” không phải tệp thường hay thư mục — có thể đó là symlink. Chúng ta sẽ quay lại trong các bài giảng nâng cao.

6. Lỗi thường gặp khi làm việc với thư mục

Lỗi số 1: cố xóa thư mục không rỗng bằng lời gọi Files.delete(path). Java sẽ ném DirectoryNotEmptyException. Hãy xóa nội dung trước, sau đó xóa chính thư mục.

Lỗi số 2: quên đóng stream từ Files.list(). Nếu không dùng try‑with‑resources, stream sẽ vẫn mở và trên Windows có thể phát sinh lỗi khi xóa thư mục.

Lỗi số 3: tạo thư mục mà không kiểm tra sự tồn tại của thư mục cha. Gọi Files.createDirectory cho đường dẫn dạng parent/child khi parent chưa tồn tại sẽ dẫn tới NoSuchFileException. Hãy dùng Files.createDirectories.

Lỗi số 4: dùng đường dẫn tuyệt đối khi không cần thiết. Ưu tiên đường dẫn tương đối trong dự án — mã sẽ dễ di chuyển hơn.

Lỗi số 5: không xử lý IOException. Bất kỳ thao tác với hệ thống tệp nào cũng có thể thất bại. Hãy bọc trong try-catch hoặc ném ngoại lệ lên tầng cao hơn.

Lỗi số 6: cố tạo/xóa trong thư mục mà không có quyền. Trường hợp này sẽ nhận AccessDeniedException. Hãy kiểm tra ngữ cảnh chạy và quyền truy cập.

1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Tổ chức báo cáo: Thư mục theo năm 📂
Tổ chức báo cáo: Thư mục theo năm 📂
1
Nhiệm vụ
JAVA 25 SELF, mức độ, bài học
Đã khóa
Kiểm kê kho tài sản trò chơi 📦
Kiểm kê kho tài sản trò chơi 📦
1
Khảo sát/đố vui
, cấp độ , bài học
Không có sẵn
Làm việc với tệp
Làm việc với tệp
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION