Java: Các hoạt động với File

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Lớp Files là một entrypoint chính của gói java.nio.file. Lớp này cung cấp một tập phong phú các phương thức tĩnh để đọc, ghi, và thao tác với các tập tin và thư mục. Các phương thức của Files làm việc với các đối tượng của lớp Path. Bài viết này ta sẽ tìm hiểu về các chủ đề:

  • Giải phóng tài nguyên hệ thống
  • Bắt ngoại lê
  • Varargs
  • Các hoạt động Atomic
  • Thay đổi phương thức
  • Glob là gì?
  • Nhận diện liên kết

Giải phóng tài nguyên hệ thống

Có khá nhiều tài nguyên được sử dụng trong API này, chẳng hạn như các stream hoặc các channel, thực thi hoặc thừa kế giao diện java.io.Closeable. Một yêu cầu tài nguyên Closeable là phương thức close phải được gọi để giải phóng tài nguyên khi nó không còn cần thiết nữa. Nếu không đóng tài nguyên lại thì có thể ảnh hướng đến hiệu hiệu năng của ứng dụng. Câu lệnh try-with-resources được mô tả trong phần kế tiếp sẽ xử lý các bước này cho ta.

Bắt ngoại lệ

Đối với tập tin I/O, việc xảy ra những điều không mong muốn luôn hiện hữu: một tập tin tồn tại (hoặc không tồn tại) ngoài dự kiến, chương trình không có quyền truy cập vào hệ thống tập tin, hệ thống tập tin mặc định thực hiện không hỗ trợ một chức năng cụ thể, ...

Tất cả các phương thức truy cập vào hệ thống tập tin có thể ném ngoại lệ IOException. Đó là cách tốt nhất để bắt ngoại lệ bằng cách nhúng các phương thức này vào một khối try-with-resources đã được giới thiệu trong phiên bản Java SE 7. Khối try-with-resources có lợi thế là các trình biên dịch tự động tạo code để đóng tài nguyên khi không còn cần thiết. Dưới đây là ví dụ:

Charset charset = Charset.forName( "US-ASCII");
String s = ...;
try (BufferedWriter writer = Files.newBufferedWriter(file, charset)) {
    writer.write(s, 0, s.length()) ;
} catch(IOException x) {
    System.err.format("IOException: %s%n", x);
}

Ngoài ra, bạn có thể nhúng các phương thức I/O tập tin trong một khối try và sau đó bắt bất kỳ trường hợp ngoại lệ nào trong khối catch. Nếu mã của bạn đã mở bất kỳ một stream hay channel nào thi ta nên đóng chúng trong khối finally. Ví dụ trên sẽ sửa lại như sau:

Charset charset = Charset.forName( "US-ASCII");
String s = ...;
BufferedWriter writer = null;
try {
    writer = Files.newBufferedWriter(file, charset);
    writer.write(s, 0, s.length());
} catch(IOException x) {
    System.err.format("IOException: %sn%", x);
} finally {
    if (write != null)
      writer.close();
}

Ngoài IOException còn có nhiều loại ngoại lệ khác thừa kế từ FileSystemException. Lớp này có một số phương thức hữu ích, chẳng hạn như phương thức getfile cho phép trả lại tập tin đã cung cấp, phương thức getMessage trả về chuỗi tin nhắn chi tiết, getReason trả về lý do tại sao các hoạt động hệ thống tập tin thất bại, ...

Đoạn mã sau đây trình bày cách sử dụng phương thức getfile:

try (...) {
    ...    
} catch(NoSuchFileException x) {
    System.err.format("%s không tồn tại \n", x.getFile());
}

Varargs

Một số phương thức của Files chấp nhận một số lượng tùy ý của các đối số khi các cờ hiệu được quy định. Ví dụ, trong chữ ký phương thức sau đây, ký hiệu 3 chấm (...) đặt sau đối số CopyOption chỉ ra rằng phương thức chấp nhận một số lượng đối số bất ký có kiểu CopyOption, hoặc thường gọi là varargs:

Path Files.move(Path, Path, CopyOption...)

Khi một phương thức chấp nhận một đối số varargs thì ta có thể truyền tới nó một danh sách các giá trị phân cách nhau bằng dấu phẩy hoặc một mảng( CopyOption[]) của các giá trị.

Ví dụ dưới đây cho thấy phương thức move() ở trên có thể được gọi như sau:

import static java.nio.file.StandardCopyOption.*;

Path path = ...;
Path target = ...;
Files.move(path, target, REPLACE_EXISTING, ATOMIC_MOVE);

Các hoạt động Atomic

Cos một số phương thức Files, chẳng hạn như move, có thể thực hiện một số hoạt động atomic trong một số hệ thống tập tin.

Một hoạt động tập tin atomic là một hoạt động mà không bị gián đoạn hoặc chỉ thực hiện được "một phần", hoặc là toàn bộ hoạt động được thực hiện thành công hoặc hoạt động không thành. Điều này rất quan trọng khi ta có nhiều tiến trình hoạt động trên cùng một khu vực của hệ thống tập tin, và ta cần phải đảm bảo rằng mỗi tiến trình phải truy cập một tập tin hoàn chỉnh.

Thay đổi phương thức

Có nhiều phương thức I/O tập tin hỗ trợ phương pháp xâu chuỗi phương thức.

Đầu tiên ta gọi một phương thức và nó trả về một đối tượng, sau đó ta ngay lập tức gọi một phương thức khác trên đối tượng đó, phương thức này cũng trả về một đối tượng nữa, điều này gọi là xâu chuỗi phương thức. Có nhiều ví dụ I/O sử dụng kỹ thuật sau đây:

String value = Charset.defaultCharset().decode(buf).ToString();.
UserPrincipal group = file.
                                getFileSystem().
                                getUserPrincipalLookupService().
                                lookupPrincipalByName ( "tôi");

Kỹ thuật này tạo ra mã nhỏ gọn và cho phép ta tránh được việc phải khai báo các biến tạm mà ta không cần đến sau đó.

Glob là gì?

Hai phương thức trong một lớp Files chấp nhận một đối số glob, nhưng glob là gì?

Ta có thể sử dụng cú pháp glob để xác định dữ liệu có tương thích với mẫu hay không.

Một mẫu glob được quy định như một chuỗi và được ghép nối với các chuỗi khác, chẳng hạn như thư mục hoặc tên tập tin. Cú pháp glob thường có một số quy tắc đơn giản sau:

  • Dấu * : tương ứng với một chuỗi bất kỳ (kể cả chuỗi rỗng).
  • Hai dấu  ** : hoạt động giống như * nhưng vượt qua ranh giới thư mục. Cú pháp này thường được áp dụng với đường dẫn đầy đủ.
  • Dấu ? : tương ứng với một ký tự chính xác.
  • Cặp ngoặc xoắn {} : chỉ định một tập hợp các mẫu con. Ví dụ:
    • {sun,moon,stars} tương đương với "sun", "moon", hoặc "stars".
    • {temp*, tmp*} tương ứng với tất cả các chuỗi bắt đầu với "temp" hoặc "tmp".
  • Cặp ngoặc vuông [] : tương ứng với một tập hợp các ký tự đơn lẻ, khi dấu gạch ngang (-) được sử dụng thì đương đương với một dãy ký tự. Ví dụ:
    • [aeiou] tương ứng với bất kỳ ký tự nguyên âm thường nào.
    • [0-9] tương ứng với một ký số bất kỳ.
    • [A-Z] tương ứng với khớp với bất kỳ ký tự in hoa nào.
    • [a-z,A-Z] tương ứng với bất kỳ ký tự in thường hoặc in hoa nào.
    Trong cặp ngoặc vuông ta cũng có quyền sử dụng những ký tự như *?, và \ để thiết lập mẫu.
  • \ : biến ký tự đặc biệt ngay sau nó thành ký tự thông thường.
  • Tất cả các ký tự còn lại đều tương đương với chính nó (a là a, b là b, ...).
  • Nếu muốn chuyển các ký tự đặc biệt thành ký tự thông thường, ta sử dụng các ký tự sổ ngược đặt trước ký tự đặc biệt đó, ví dụ: \\ tương ứng với một dấu gạch chéo thông thường, \? tương ứng với dấu hỏi, \* tương ứng với dấu hoa thị thông thường.

Dưới đây là một số ví dụ về cách dùng glob:

  • *.html - tương ứng với một chuỗi bất kỳ kết thúc bằng .html
  • ??? - tương ứng với một chuỗi bất kỳ có đúng ba chữ cái hay chữ số (abc, 123,...)
  • *[0-9]* - Tương ứng với một chuỗi bất kỳ có chứa ít nhất một giá trị số
  • *.{htm,html,pdf} - Tương ứng với một chuỗi bất kỳ kết thúc với .htm.html hoặc .pdf
  • a?*.java - Tương ứng với một chuỗi bắt đầu bằng a, tiếp theo là ít nhất một chữ cái hay chữ số, và kết thúc là .java
  • {foo*,*[0-9]*} - Tương ứng với một chuỗi bất kỳ bắt đầu bằng foo hoặc một chuỗi bất kỳ chứa ít nhất một giá trị số.

Lưu ý:  Nếu ta đang gõ những mẫu glob từ bàn phím và nó có chứa một trong các ký tự đặc biệt thì ta phải đặt nó vào cặp nháy kép (chẳng hạn như "*"), sử dụng dấu xổ ngược (\*), hoặc sử dụng bất cứ cơ chế escape được hỗ trợ tại dòng lệnh.

Cú pháp glob rất mạnh mẽ và dễ sử dụng. Tuy nhiên, nếu nó không đáp ứng đầy đủ cho nhu cầu của bạn, bạn cũng có thể sử dụng một biểu thức chính quy (regular expression). Để biết thêm thông tin, xin xem thêm bài viết về Regular Expressions.

Để biết thêm thông tin về các cú pháp glob, xin xem các đặc điểm kỹ thuật API của phương thức getPathMatcher trong lớp FileSystem.

Nhận diện liên kết

Lớp Files là một "nhận diện liên". Theo đó, mỗi một phương thức trong lớp Files hoặc là xác định được phải làm gì khi gặp phải một liên kết tượng trưng, hoặc nó cung cấp một tùy chọn cho phép ta cấu hình các hành vi khi gặp phải liên kết tượng trưng.

» Tiếp: Kiểm tra tập tin hoặc thư mục
« Trước: Lớp Path
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!