Khi Oracle tung ra phiên bản Java 7 - một phiên bản hoàn toàn được đổi mới và được nâng cấp mạnh mẽ hơn giúp cho các Java Developer đẩy mạnh năng suất viết code cao nhất. Trong 1 loạt các tính năng được thêm vào Java 7, có 1 tập các API mới được thêm vào nhằm cải tiến bộ Java IO và NIO (Java 1.4) đó là Java 7 NIO.2 APIs.

Với việc sử dụng các API NIO.2, bạn không cần phải vất vả viết mã copy file từ nơi này sang nơi khác hay thao tác với hệ thống tệp tin bằng những kỹ thuật phức tạp, .v.v....

Trong thời gian tới, tôi sẽ cố gắng viết 1 bài thật chi tiết và đưa ra những ví dụ minh họa thực tế nhất cho bộ API NIO.2 này. Tuy nhiên, trong bài viết này tôi chỉ đưa ra một ứng dụng nho nhỏ nhưng rất thiết thực đó là theo dõi hoạt động thao tác tệp tin trong 1 thư mục nào đó. Đây là 1 trường hợp mà tôi đã gặp và tìm hiểu khi ngày xưa học Java rồi join vào làm ứng dụng Text Editor.

Nếu bạn đang đọc bài viết này của tôi, có thể bạn đã từng sử dụng các IDE như: Visual Studio, PHP Design, Netbeans, Eclipse,....hay đơn giản nhất là sử dụng Notepad++ (tôi nghĩ ứng dụng này bạn sử dụng nhiều). Bạn đã từng sử dụng các phần mềm này, chắc hẳn đã từng có nhiều lần bạn sửa file source code từ 1 chương trình soạn thảo văn bản nào đó mà không phải IDE mà bạn đang làm việc, và cho tới lúc bạn quay trở lại IDE làm việc thì nó xuất hiện 1 thông báo nói cho bạn biết rằng "file source này đã được chỉnh sửa bởi 1 trình soạn thảo nào đó, bạn có muốn cập nhật nội dung source hiện tại trên IDE không?". Tôi minh họa trường hợp như sau:



Như bạn thấy, tôi soạn thảo 1 văn bản trên Notepad++ rồi save lại, xong, tôi mở bằng Notepad và thêm nội dung mới vào đó. Quay trở lại Notepad++ tôi nhận được thông báo như trên.

Cũng mất vài ngày tìm hiểu và thực nghiệm, tôi đã tìm được cách giải quyết cho vấn đề trên bằng cách sử dụng các API của NIO.2. Tất nhiên, một vấn đề thường có rất nhiều cách giải quyết để ra kết quả, không hẳn chỉ sử dụng Java NIO.2 để làm được chức năng detect giống Notepad++ như trên hay của các IDE viết mã khác mà còn có rất nhiều phương pháp khác để làm được như vậy. Quan trọng chúng ta cần phải tìm và sử dụng phương pháp nào đó nhanh, hiệu quả, thực dụng.

Để viết mã xử lý chức năng detect đó, tôi sẽ giới thiệu qua cho bạn những Class, Interface, Constants sử dụng để làm việc. Những Class, Interface, Constant này đều có Javadoc nên bạn muốn hiểu rõ và đọc chi tiết hơn thì bạn hãy đọc Javadoc mô tả của những Class, Interface, Constant đó.

Những Class, Interface mà tôi sẽ sử dụng nằm trong package java.nio.file.* - package này là package chính của NIO.2, nó sẽ chứa các Interface và Class định nghĩa các API mới dùng để truy cập tệp tin và hệ thống tệp tin.

Diễn giải các Class, Interface sử dụng:

- WatchService - là 1 interface, nó ánh xạ trực tiếp tới cơ chế thông báo sự kiện tệp tin (nếu bạn biết mẫu Observer trong Design Pattern thì sẽ hiểu khá dễ dàng).
- Path - là 1 Immutable Class (nếu chưa biết Immutable, bạn đọc ở đây) biểu diễn cho đường dẫn tới bất kỳ tệp tin nào. Ví dụ như: /home/code4lifevn (Ubuntu), G:\Code4lifeVn\demo (Windows).
- Paths - là 1 Class, lớp này bao gồm các phương thức static có nhiệm vụ trả về 1 đối tượng Path bằng cách convert 1 chuỗi đường dẫn hoặc URI.
- FileSystem - đây là lớp đại diện cho hệ thống tệp tin, được sử dụng để có được đường dẫn đến các tệp tin.
- FileSystems - đây là lớp chứa Factory Method trả về đối tượng FileSystem. Lớp này định nghĩa phương thức getDefault() để trả về hệ thống tệp tin mặc định và các phương thức để xây dựng các hệ thống tệp tin khác nhau.
- StandardWatchEventKinds - đây là lớp định nghĩa các loại event chuẩn bao gồm:
+ ENTRY_CREATE (detect có file được tạo)
+ ENTRY_DELETE (detect có file bị xóa)
+ ENTRY_MODIFY (detect có file được sửa)
+ OVERFLOW
- WatchKey - đây là 1 interface đại diện cho kết quả đăng ký của đối tượng Path, kết quả đăng ký thành công WatchKey sẽ ở trạng thái ready và được coi là hợp lệ. Một đối tượng WatchKey duy trì tính hợp lệ cho tới khi xuất hiện 1 trong những vấn đề sau:
+ Phương thức WatchKey.cancel() được gọi.
+ Thư mục theo dõi không còn nữa.
+ Đối tượng WatchService được đóng.

(Để hiểu rõ hơn về những lớp, interface, phương thức, bạn hãy đọc Javadoc)

Thực nghiệm WatchService

Tôi sẽ làm 1 ví dụ đơn giản cho việc detect trạng thái tệp tin trong thư mục nào đó. Dựa vào kỹ thuật này bạn có thể mở rộng ra làm các ứng dụng của riêng mình như: 1 hệ thống theo dõi file được upload bởi thành viên lên host được liên tục cập nhật, theo dõi, thống kê; chức năng detect nội dung file đã được chỉnh sửa; detect và đưa ra những thông báo cho người dùng khi thao tác với tệp tin; v.v...nhiều ý tưởng nữa.

Ứng dụng đơn giản chỉ có 1 lớp chứa main để chạy thôi.

Class FileMonitor

package com.blogspot.code4lifevn.filemonitor;

import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

/**
 *
 * @author Code4LifeVn
 */
public class FileMonitor {
    public static void main(String[] args) throws IOException, InterruptedException {
        // => Lấy về đối tượng Path có đường dẫn F:
        Path folderMonitored = Paths.get("F:\\");
        
        // => Tạo đối tượng FileSystem
        FileSystem fileSystem = FileSystems.getDefault();
        
        // => Tạo đối tượng WatchService
        WatchService watchService = fileSystem.newWatchService();
        
        // => Đăng ký theo dõi sự kiện cho folderMonitored bao gồm: CREATE, DELETE, MODIFY
        folderMonitored.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
        
        boolean isValid = true;
        
        WatchKey watchKey;
        
        while(isValid) {
            watchKey = watchService.take();
            
            // => Xử lý logic cho từng sự kiện
            for (WatchEvent watchEvent : watchKey.pollEvents() /* gọi pollEvents() để lấy về List các event*/) {
                switch(watchEvent.kind().toString()) {
                    case "ENTRY_CREATE":
                        System.out.println(String.format("File %s duoc tao tren %s", watchEvent.context(), folderMonitored));
                        break;
                    case "ENTRY_DELETE":
                        System.out.println(String.format("File '%s' duoc xoa tren %s", watchEvent.context(), folderMonitored));
                        break;
                    case "ENTRY_MODIFY":
                        System.out.println(String.format("File '%s' duoc sua tren %s", watchEvent.context(), folderMonitored));
                        break;
                    default:
                }
            }
            
            isValid = watchKey.reset();
        }
    }
}

Ok, đã xong, bây giờ bạn thử chạy rồi tạo thực hiện tạo file, xóa file xem thế nào nhé. Dựa trên kỹ thuật cơ bản này, hy vọng bạn sẽ viết ra những tool phục vụ cho mục đích cá nhân của mình, lúc đó bạn sẽ thấy yêu thích Java hơn, Java không chỉ dừng lại ở những bài tập quản lý sinh viên, quản lý thư viện ở trên lớp mà bạn có thể sáng tạo ra những ứng dụng thiết thực hơn cho cuộc sống.

Demo bằng Swing GUI:


0 nhận xét:

Đăng nhận xét

 

code4lifevn team

Thanh niên nghiêm túc :)

Name: Manh Do

Age: years old

Job: Senior Java and Mobile Developer

Country: VietNam

Name: Hung Nguyen

Age: years old

Job: Android Developer

Country: VietNam

Name: Trung PH

Age: years old

Job: Senior iOS and Android Developer

Country: VietNam

Name: Điệp NT

Age: years old

Job: Senior .Net and Android Developer

Country: VietNam