CodeGym /Các khóa học /C# SELF /Lớp tĩnh File và <...

Lớp tĩnh FileDirectory

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

1. Giới thiệu

Làm việc trực tiếp với luồng (StreamReader, StreamWriter, FileStream) rất hữu ích, đặc biệt khi cần kiểm soát quá trình đọc/ghi ở mức thấp: ví dụ, ghi theo khối nhỏ từng phần hoặc xử lý file lớn thành nhiều phần.

Nhưng trong thực tế thường chỉ cần biết: "file này có tồn tại không?", "copy file từ chỗ này sang chỗ kia", "xóa file", "lấy danh sách tất cả file .txt trong thư mục", v.v. Để xử lý những việc như vậy Microsoft tạo ra hai công cụ tổng quát: các lớp tĩnh FileDirectory. Tĩnh có nghĩa là không cần tạo instance, gọi trực tiếp phương thức trên tên lớp.

Tương tự đời thường

Nếu luồng là bạn với cây bút chì đang viết từng chữ lên giấy, thì FileDirectory giống như cái bàn có ngăn kéo: bạn có thể "mở ngay" một ngăn (Directory), lấy tờ giấy ra (File.ReadAllText), vứt tờ giấy đi (File.Delete) hoặc kéo cả ngăn đi chỗ khác (Directory.Move). Việc đơn giản thì phương thức đơn giản.

2. Lớp File: nó là gì và để làm gì

Lớp File có một bộ phương thức tĩnh rất tiện cho các thao tác phổ biến với file.

Các phương thức được dùng nhiều nhất

Phương thức Mô tả
File.Exists(path)
Kiểm tra xem file có tồn tại theo đường dẫn không
File.ReadAllText(path)
Đọc toàn bộ file dưới dạng text
File.ReadAllLines(path)
Đọc tất cả các dòng của file vào mảng
File.WriteAllText(path, text)
Ghi đè file, ghi text
File.AppendAllText(path, text)
Thêm text vào cuối file
File.Copy(source, destination)
Copy file
File.Delete(path)
Xóa file
File.Move(source, destination)
Di chuyển hoặc đổi tên file
File.Open/Read/Write/Create
Mở stream cho các thao tác phức tạp

Ví dụ nhanh: kiểm tra file và đọc nó

string filePath = "data.txt";

if (File.Exists(filePath))
{
    string content = File.ReadAllText(filePath);
    Console.WriteLine("Nội dung file:");
    Console.WriteLine(content);
}
else
{
    Console.WriteLine("Không tìm thấy file!");
}

Thấy chưa? Không cần quản lý stream thủ công cho trường hợp đơn giản!

3. Lớp Directory: quản lý thư mục không đau đớn

Nếu File là về file đơn lẻ, thì Directory là về thư mục (directory).

Nhiệm vụ chính

Phương thức Mô tả
Directory.Exists(path)
Kiểm tra xem thư mục tồn tại không
Directory.CreateDirectory(path)
Tạo thư mục (hoặc cả đường dẫn với các thư mục con)
Directory.Delete(path)
Xóa thư mục (có thể kèm subdirectories)
Directory.GetFiles(path)
Lấy danh sách file trong thư mục
Directory.GetDirectories(path)
Lấy danh sách thư mục con
Directory.Move(source, destination)
Di chuyển hoặc đổi tên thư mục
Directory.GetCurrentDirectory()
Lấy current working directory của ứng dụng

Ví dụ: tạo thư mục và lưu file vào đó

string dirPath = "Results";
if (!Directory.Exists(dirPath))
{
    Directory.CreateDirectory(dirPath);
    Console.WriteLine("Thư mục 'Results' đã được tạo.");
}

string filePath = Path.Combine(dirPath, "summary.txt");
File.WriteAllText(filePath, "Dữ liệu tổng kết: ...");

Console.WriteLine($"File {filePath} đã được ghi.");

4. Các kịch bản điển hình dùng FileDirectory

Các phương thức cơ bản có vẻ chán nếu không thấy chúng trong thực tế! Hãy xem cách dùng các lớp này để giải quyết bài toán thực tế và, tiện thể, phát triển ứng dụng ví dụ của chúng ta (hãy tưởng tượng ta làm hệ thống todo-list đơn giản, lưu kết quả trong file).

Lưu dữ liệu vào file (thay thế file cũ)

// Lưu danh sách công việc vào file
string[] todos = { "Mua bánh mì", "Gọi bác sĩ", "Làm bài tập về nhà C#" };
string filePath = "todo.txt";
File.WriteAllLines(filePath, todos);

Console.WriteLine("Danh sách công việc đã được lưu.");

Tải dữ liệu từ file

// Tải công việc nếu file tồn tại
if (File.Exists(filePath))
{
    string[] loadedTodos = File.ReadAllLines(filePath);
    Console.WriteLine("Danh sách công việc của bạn:");
    foreach (var task in loadedTodos)
    {
        Console.WriteLine("- " + task);
    }
}
else
{
    Console.WriteLine("Bạn chưa có danh sách công việc.");
}

Thêm công việc mới (không ghi đè file)

string newTask = "Dắt chó đi dạo";
File.AppendAllText(filePath, newTask + Environment.NewLine);
Console.WriteLine("Đã thêm công việc!");

Copy và backup file

string backupPath = "todo_backup.txt";
File.Copy(filePath, backupPath, overwrite: true);
Console.WriteLine("Đã tạo bản sao lưu danh sách công việc.");

Di chuyển (hoặc đổi tên) file

string archivePath = "todo_archive.txt";
File.Move(filePath, archivePath);
Console.WriteLine("Danh sách công việc đã được lưu trữ (đổi tên).");

Xóa file

if (File.Exists(archivePath))
{
    File.Delete(archivePath);
    Console.WriteLine("Đã xóa bản lưu — giải phóng chỗ!");
}

5. Làm việc với thư mục: ví dụ

Tạo cây thư mục

string path = Path.Combine("Reports", "2024", "June");
Directory.CreateDirectory(path);
Console.WriteLine($"Thư mục {path} đã được tạo (bao gồm các thư mục trung gian).");

Lấy danh sách file và thư mục

string dirPath = "Reports";
if (Directory.Exists(dirPath))
{
    string[] files = Directory.GetFiles(dirPath);
    Console.WriteLine("Các file trong thư mục:");
    foreach (var file in files)
    {
        Console.WriteLine(file);
    }

    string[] subDirs = Directory.GetDirectories(dirPath);
    Console.WriteLine("Thư mục con:");
    foreach (var dir in subDirs)
    {
        Console.WriteLine(dir);
    }
}

Lọc file theo mẫu (chỉ txt)

string[] txtFiles = Directory.GetFiles(dirPath, "*.txt");
Console.WriteLine("Chỉ các file .txt:");
foreach (var file in txtFiles)
{
    Console.WriteLine(file);
}

Duyệt đệ quy (file trong tất cả thư mục con)

string[] allFiles = Directory.GetFiles(dirPath, "*.*", SearchOption.AllDirectories);
Console.WriteLine("Các file trong tất cả thư mục con:");
foreach (var file in allFiles)
{
    Console.WriteLine(file);
}

Di chuyển và xóa thư mục

string from = "OldReports";
string to = "Archive/OldReports";
if (Directory.Exists(from))
{
    Directory.Move(from, to);
    Console.WriteLine($"Thư mục {from} đã được di chuyển tới {to}");
}

if (Directory.Exists(to))
{
    Directory.Delete(to, recursive: true); // true: xóa toàn bộ bên trong
    Console.WriteLine($"Thư mục {to} đã bị xóa (kèm nội dung).");
}

6. Các điểm hay hữu ích

Tích hợp với đường dẫn: lớp Path

Khi làm việc với file và thư mục thường phải ghép đường dẫn đầy đủ, nối tên thư mục và file, tách extension, kiểm tra ký tự hợp lệ. Dùng lớp trợ giúp Path.

Ví dụ

string folder = "Results";
string filename = "week1.txt";
string fullPath = Path.Combine(folder, filename); // ghép an toàn!
Console.WriteLine(fullPath); // "Results/week1.txt" (hoặc "\" trên Windows)
  • Lấy phần mở rộng của file: Path.GetExtension(fullPath)
  • Lấy tên file không kèm đường dẫn: Path.GetFileName(fullPath)

Dùng Path.Combine thay vì nối chuỗi — an toàn hơn cho ứng dụng đa nền tảng.

Phương thức "mọi thứ cùng lúc" vs phương thức luồng

Nhiều phương thức của FileDirectory (ví dụ File.ReadAllText, File.WriteAllText, Directory.GetFiles) làm xong công việc "nguyên cái": đọc/ghi/lấy danh sách file trong một lần. Rất tiện, nhưng không phù hợp cho file hoặc thư mục rất lớn, nơi có thể hết bộ nhớ. Nếu làm việc với hàng GB — chuyển sang các lớp luồng (StreamReader, StreamWriter, FileStream, v.v.) hoặc xử lý theo phần.

Khi dùng File/Directory, khi dùng classes luồng

Tình huống Nên dùng
Cần kiểm tra file/thư mục có tồn tại
File.Exists, Directory.Exists
Đọc/ghi toàn bộ file nhỏ
File.ReadAllText, WriteAllText
Thêm text vào cuối file
File.AppendAllText
Lấy danh sách file trong thư mục
Directory.GetFiles
Copy, xóa, di chuyển file
File.Copy/Delete/Move
Copy/xóa cả thư mục Directory.Delete/Move/Copy (Copy — cần thư viện bên thứ 3)
Xử lý file RẤT lớn theo phần Các lớp luồng (StreamReader, FileStream)

Ý nghĩa thực tế và ứng dụng

  • Tải/luu cấu hình nhanh, settings, file JSON/XML.
  • Hệ thống logging (ghi log ra đĩa).
  • Tiện ích sao lưu đơn giản (backup) và di chuyển dữ liệu.
  • Quét thư mục chứa multimedia, ảnh, tài liệu.
  • Kịch bản người dùng: tải template, export/import, tạo báo cáo, v.v.

Các bài tập phỏng vấn thực tế cũng thường yêu cầu dùng chính các lớp này: "Cài đặt hàm tính tổng kích thước tất cả file .txt trong thư mục", "Tạo bản sao lưu file vào thư mục riêng", v.v.

Sơ đồ nhanh: khi dùng phương thức nào

graph TD
    A[Bạn muốn làm gì?]
    A -->|Kiểm tra tồn tại| B[File.Exists hoặc Directory.Exists]
    A -->|Đọc/ghi file nguyên cái| C[File.ReadAllText/WriteAllText]
    A -->|Thêm dữ liệu vào file| D[File.AppendAllText]
    A -->|Làm việc với thư mục| E[Directory.CreateDirectory, GetFiles, GetDirectories]
    A -->|Copy/xóa/di chuyển file| F[File.Copy/Delete/Move]
    A -->|Copy/xóa thư mục nguyên cái| G[Directory.Delete/Move]

7. Đặc điểm và lỗi hay gặp

Kiểm tra tồn tại và "race condition". Ngay cả khi kiểm tra file/thư mục tồn tại, giữa lần kiểm tra và khi thực hiện thao tác có thể có tiến trình khác thay đổi nó. Vì vậy luôn dùng try-catch ngay cả khi đã kiểm tra tồn tại!

Quyền truy cập. Nếu ứng dụng không có quyền đọc/ghi/xóa, phương thức sẽ ném UnauthorizedAccessException.

Đường dẫn quá dài. Độ dài tối đa của đường dẫn (thường là 260 ký tự trên Windows cũ; trong .NET 9 giới hạn mềm hơn, nhưng vẫn cẩn thận).

Bắt lỗi. Các phương thức như File.ReadAllText hoặc Directory.GetFiles không khoan nhượng: nếu file/thư mục không tồn tại — sẽ throw exception ngay. Bọc bằng try-catch hoặc kiểm tra tồn tại trước.

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