1. Giới thiệu
Có vẻ tệp là thứ đơn giản, và tạo tệp thì dễ như ăn bánh: chỉ cần click chuột phải (trên Windows). Nhưng trong dự án thực tế, việc tạo và xóa tệp bằng code là chìa khóa để tự động hóa và linh hoạt. Ví dụ:
- Trong trình soạn thảo văn bản, người dùng nhấn "Save" — và code của bạn tạo tệp mới để ghi lại tác phẩm.
- Hệ thống logging tự động tạo các tệp log khi ứng dụng khởi động.
- Chương trình nén hoặc utility backup đều tạo tệp tạm thời rồi xóa chúng sau.
- Game viết bằng C# làm autosave — tạo hoặc ghi đè file save.
- Và bạn (hoặc script của bạn) tự động dọn thư mục khỏi các tệp tạm cũ để khỏi đầy ổ.
Biết cách tạo và xóa tệp tự động là một trong những kỹ năng nền tảng của dev .NET hiện đại.
2. Thao tác nhanh qua File
Tạo tệp
Trong C# có nhiều cách tạo tệp. Cách nhanh nhất và đơn giản nhất là dùng lớp tĩnh File. Thử xem:
// Tạo tệp rỗng "myfile.txt" trong thư mục hiện tại
File.Create("myfile.txt").Close(); // Cần đóng FileStream!
Console.WriteLine("Tệp 'myfile.txt' đã được tạo.");
Lưu ý quan trọng:
Phương thức File.Create trả về đối tượng FileStream, phải đóng (Close()) để hệ điều hành không phàn nàn rằng tệp "đang dùng". Nếu không đóng, một số thao tác sau đó với cùng tệp có thể không hoạt động. Vấn đề kinh điển: "Tệp đang được sử dụng bởi tiến trình khác", mặc dù tiến trình đó chính là chương trình của bạn chưa đóng stream.
Nếu tệp đã tồn tại, File.Create sẽ ghi đè nó (tệp cũ bị thay bằng tệp mới rỗng). Nếu chưa có — tệp sẽ xuất hiện.
File rỗng để làm gì?
Thường thì tệp mới không chỉ để trống, mà để ghi thứ gì đó vào. Có các phương thức tiện dụng cho việc này:
File.WriteAllText("welcome.txt", "Xin chào, thế giới tệp!");
Lệnh này sẽ tạo tệp, ghi chuỗi vào đó, và đóng tệp gọn gàng để không có rắc rối về sau.
Kiểm tra tồn tại của tệp
Trước khi tạo tệp mới, tốt nhất kiểm tra xem tệp đã tồn tại chưa. Nếu không thì có nguy cơ vô tình ghi đè dữ liệu quan trọng.
if (!File.Exists("important.txt"))
{
File.WriteAllText("important.txt", "Lưu thông tin quan trọng.");
Console.WriteLine("Tệp đã được tạo.");
}
else
{
Console.WriteLine("Tệp này đã tồn tại, nên nghĩ phương án khác!");
}
3. Ví dụ thực tế: "Lưu lời chào người dùng"
Console.Write("Nhập tên của bạn: ");
string name = Console.ReadLine();
string filename = $"{name}_greeting.txt";
string message = $"Chào mừng, {name}!";
// Kiểm tra xem tệp đã tồn tại chưa
if (!File.Exists(filename))
{
File.WriteAllText(filename, message);
Console.WriteLine($"Tệp chào mừng cá nhân {filename} đã được tạo.");
}
else
{
Console.WriteLine($"Tệp {filename} đã tồn tại! Ghi đè? (y/n)");
string answer = Console.ReadLine();
if (answer?.ToLower() == "y")
{
File.WriteAllText(filename, message);
Console.WriteLine($"Tệp {filename} đã được ghi đè.");
}
else
{
Console.WriteLine("Giữ nguyên như cũ.");
}
}
Chúng ta làm gì ở đây:
- Kiểm tra xem tệp có tồn tại (File.Exists).
- Nếu chưa có — tạo và ghi nội dung (File.WriteAllText).
- Nếu có — hỏi người dùng có muốn ghi đè hay không.
4. Xóa tệp
Xóa tệp trong C# gần như một hành động hacker nhưng vẫn an toàn! Ở đây cũng đơn giản thôi:
Dùng File.Delete
File.Delete("myfile.txt");
Nếu tệp không tồn tại — không có drama! Chẳng có lỗi gì (miễn là đường dẫn hợp lệ).
Bẫy dành cho người mới
- Nếu tệp đang được mở bởi chính chương trình bạn (hoặc chương trình khác), sẽ ném ngoại lệ.
- Nếu đường dẫn sai — sẽ xuất hiện ArgumentException.
Khuyến nghị: luôn kiểm tra tồn tại
if (File.Exists("victim.txt"))
{
File.Delete("victim.txt");
Console.WriteLine("Tệp đã bị xóa.");
}
else
{
Console.WriteLine("Không có gì để xóa — tệp đó không tồn tại.");
}
5. Thư mục và tệp: tạo cấu trúc tệp
Tạo tệp trong thư mục
string folder = "Data";
Directory.CreateDirectory(folder); // nếu thư mục chưa có — sẽ được tạo
string filename = Path.Combine(folder, "info.txt");
File.WriteAllText(filename, "Đây là thông điệp bí mật!");
Quan trọng: Nếu cố tạo tệp trong thư mục không tồn tại sẽ ném ngoại lệ. Vậy nên gọi Directory.CreateDirectory(folder) trước. Nó sẽ không tạo lại thư mục nếu đã có, nên gọi an toàn.
6. Làm việc với instance: FileInfo
Cho các tình huống "cổ điển" hoặc hơi nâng cao hơn, lớp FileInfo rất hữu ích:
FileInfo fi = new FileInfo("example.txt");
// Tạo tệp mới (giống File.Create — tạo tệp rỗng)
using (var fs = fi.Create())
{
// có thể ghi gì đó nếu muốn
}
Console.WriteLine($"Tệp 'example.txt' đã được tạo bằng FileInfo.");
Xóa qua FileInfo:
FileInfo fi = new FileInfo("oldfile.txt");
if (fi.Exists)
{
fi.Delete();
Console.WriteLine("Tệp đã được xóa bằng FileInfo.");
}
Ưu điểm của FileInfo
Nếu bạn định làm nhiều hơn chỉ tạo/xóa — ví dụ truy xuất thuộc tính tệp hoặc thực hiện nhiều thao tác trên cùng tệp — cách dùng instance tiện hơn (và đôi khi hiệu năng tốt hơn).
7. Tạo và dọn "tệp kỹ thuật"
Giả sử ứng dụng lưu tệp tạm trong thư mục "temp_data", và ta muốn xóa tất cả tệp trong đó có tên bắt đầu bằng "temp_".
string tempFolder = "temp_data";
Directory.CreateDirectory(tempFolder);
for (int i = 1; i <= 5; i++)
{
string tempFile = Path.Combine(tempFolder, $"temp_{i}.txt");
File.WriteAllText(tempFile, $"Dữ liệu thử nghiệm {i}");
}
Console.WriteLine("Đã tạo 5 tệp tạm.");
// Giờ xóa tất cả temp_*.txt
foreach (string file in Directory.GetFiles(tempFolder, "temp_*.txt"))
{
File.Delete(file);
Console.WriteLine($"Đã xóa tệp: {file}");
}
Rất hữu dụng để tự động dọn các tệp tạm thời hoặc cũ.
8. Chi tiết quan trọng: ngoại lệ và an toàn
Những gì có thể sai:
- Không có quyền ghi/xóa trong thư mục (ví dụ C:\Windows).
- Tệp đang bị chương trình khác (hoặc chính bạn!) mở.
- Đường dẫn chứa ký tự không hợp lệ (ví dụ *?<>).
- Tệp bị xóa bởi tiến trình khác giữa lúc bạn kiểm tra và lúc bạn xóa (có thể xảy ra!).
Cách bảo vệ
Trong code "thực chiến" những thao tác này luôn nên được bọc trong khối try-catch:
try
{
File.Delete("trickyfile.txt");
Console.WriteLine("Tệp đã bị xóa.");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("Không có quyền xóa tệp.");
}
catch (IOException ex)
{
Console.WriteLine("Tệp có thể đang được sử dụng bởi tiến trình khác.");
}
catch (Exception ex)
{
Console.WriteLine($"Lỗi: {ex.Message}");
}
9. Mẹo hữu ích
Những tệp luôn cần kiểm soát
- Dùng Path.Combine để ghép đường dẫn. Khi đó sẽ không gặp vấn đề với slash thừa hay thiếu, và code dễ chạy đa nền tảng hơn.
- Kiểm tra tồn tại tệp trước khi tạo/xóa, nếu không muốn bất ngờ.
- Bọc code trong try-catch khi chạy ở môi trường thực, đặc biệt ứng dụng "đa người dùng".
- Với các thao tác lặp lại trên cùng 1 tệp dùng FileInfo, thao tác đơn lẻ thì dùng File.
- Đừng để tệp mở lâu hơn cần thiết. Đang mở tệp? Hỏi bản thân: "Tại sao?" và đóng nó đi! Dùng using khi có thể.
Sổ tay kỹ thuật
| Thao tác | Phương thức | Ghi chú |
|---|---|---|
| Tạo tệp rỗng | |
Trả về FileStream, cần đóng nó |
| Ghi văn bản vào tệp | |
Tạo tệp hoặc ghi đè |
| Kiểm tra tồn tại | |
Trả về bool |
| Xóa tệp | |
Không ném ngoại lệ nếu tệp không tồn tại |
| Tạo tệp trong thư mục | |
Đảm bảo thư mục tồn tại |
| Làm việc với FileInfo | |
Dùng cho nhiều thao tác trên cùng tệp |
10. Lỗi điển hình khi làm việc với tệp
Lỗi #1: quên đóng stream sau File.Create.
Nhiều người mới tạo tệp bằng File.Create nhưng không đóng stream trả về. Kết quả là code sau đó "không thấy" tệp — như thể nó rơi vào vũ trụ song song. Hãy đóng stream rõ ràng (Close()) hoặc dùng cấu trúc using.
Lỗi #2: cố tạo tệp trong thư mục không tồn tại.
Bẫy thường gặp — cố tạo tệp trong thư mục chưa có. Đừng quên gọi Directory.CreateDirectory trước. Việc này hoàn toàn an toàn: nếu thư mục đã có thì không làm gì thêm, còn nếu chưa có thì sẽ tạo.
Lỗi #3: xóa tệp mà không kiểm tra.
Đôi khi muốn gọi File.Delete ngay mà không kiểm tra tồn tại. Điều đó chấp nhận được — phương thức không ném lỗi nếu tệp không có. Nhưng nếu đường dẫn sai hoặc không có quyền thì sẽ có ngoại lệ. Tốt hơn là chuẩn bị xử lý trước.
Lỗi #4: nhầm lẫn File.Delete và Directory.Delete.
File.Delete chỉ dùng cho tệp, còn Directory.Delete cho thư mục. Cố dùng File.Delete để xóa thư mục giống như cố dùng bàn chải đánh răng để đánh bóng gạch: về mặt kỹ thuật có thể gây rắc rối, nhưng chắc chắn không phải cách làm hợp lý.
GO TO FULL VERSION