天天看點

Java NIO.2NIO.2Path, Paths, FilesFileVisitorWatchService檔案屬性

Java NIO.2

  • NIO.2
  • Path, Paths, Files
  • FileVisitor
  • WatchService
  • 檔案屬性

NIO.2

Java7 對NIO進行了改進:

  1. 新增

    java.nio.file

    包,提供全面的檔案IO和檔案系統通路;
  2. 基于異步Channel的IO,在

    java.nio.channels

    下增加 Asynchronous開頭的Channel接口和類。

Path, Paths, Files

NIO.2 引入Path接口。代表平台無關的路徑。

增加了 Files 和 Paths 兩個工具類。

Path path = Paths.get(".");
        //包含路徑名的數量
        System.out.println(path.getNameCount());
        // null
        System.out.println(path.getRoot());

        //絕對路徑
        Path absolutePath = path.toAbsolutePath();
        System.out.println(absolutePath);
        System.out.println(absolutePath.getRoot());
        System.out.println(absolutePath.getNameCount());

        //多個連接配接路徑
        Path path1 = Paths.get("/", "Users", "data");
        System.out.println(path1);

           

Files工具類, 操作檔案

//複制檔案
        Path path2 = Paths.get("abc.txt");
        Files.copy(path2, new FileOutputStream("abc2.txt"));
        //是否為隐藏檔案
        System.out.println(Files.isHidden(path2));
        //讀取檔案所有行
        List<String> lines = Files.readAllLines(path2, Charset.forName("utf-8"));
        System.out.println(lines);
        //檔案大小
        System.out.println(Files.size(path2));
        //寫入檔案
        List<String> list = new ArrayList<>();
        list.add("張三");
        list.add("李四");
        Files.write(Paths.get("name.txt"), list, Charset.forName("utf-8"));

        //使用Stream API
        Files.list(Paths.get(".")).forEach(path3 -> System.out.println(path3));
        Files.lines(path2, Charset.forName("utf-8")).forEach(line -> System.out.println(line));

        //磁盤空間
        FileStore fileStore = Files.getFileStore(path2);
        System.out.println(fileStore.getTotalSpace());
        System.out.println(fileStore.getUsableSpace());
        
           

FileVisitor

Files工具類提供了周遊檔案和目錄的方法:

walkFileTree(): 周遊檔案和子目錄, 可以設定maxDepth深度。

需要 FileVisitor參數,代表一個檔案通路器。

FileVisitor 中定義下面方法:

  • postVisitDirectory(): 通路子目錄後觸發
  • preVisitDirectory():通路子目錄前
  • visitFile() : 通路檔案時觸發
  • visitFileFailed(): 通路檔案失敗觸發

    這四個方法都傳回 FileVisitResult 對象, 是一個枚舉類, 代表後續行為:

  • CONTINUE: 繼續
  • SKIP_SIBLINGS: 繼續, 但不放問兄弟檔案或目錄
  • SKIP_SUBTREE: 繼續, 但不放問子目錄樹
  • TERMINATE: 中支
Files.walkFileTree(Paths.get("."), new SimpleFileVisitor<Path>(){
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println("visit :" + file);
                if (file.endsWith("FliesTest.java")){
                    System.out.println("found it");
                    return FileVisitResult.TERMINATE;
                }
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                System.out.println("visit DIR: " + dir);
                return FileVisitResult.CONTINUE;
            }
        });
        
           

WatchService

NIO.2的 Path 類提供一個監聽檔案系統的變化。

register(WatchService watcher, WatchEvent)

WatchService 代表監聽服務。

注冊完調用下面方法擷取監聽檔案的變化:

  • poll(): 擷取下一個WatchKey, 可以設定等待時間
  • take():擷取下一個WatchKey, 沒有就一直等待
WatchService watchService = FileSystems.getDefault().newWatchService();
        Paths.get(".").register(watchService,
                StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_MODIFY,
                StandardWatchEventKinds.ENTRY_DELETE);
        //死循環
        while (true){
            //擷取下一個watchkey, 沒有就等待
            WatchKey key = watchService.take();
            for (WatchEvent<?> event : key.pollEvents()){
                System.out.println(event.context() + " : " + event.kind());
            }
            //重設WatchKey
            boolean valid = key.reset();
            if(!valid){
                break;
            }
        }
           

檔案屬性

NIO.2在 java.nio.file.attribute下提供了大量工具類, 用于處理檔案的屬性。

XxxAttributeView : 檔案屬性視圖

XxxAttributes: 檔案屬性集合。

FileAttributeView 接口下面的父接口:

AclFileAttributeView: 檔案的ACL權限資訊 Access Control List

BasicFileAttributeView: 基本屬性

DosFileAttributeView : DOS相關屬性, 是否隻讀, 隐藏,系統檔案,

FileOwnerFileAttributeView: 檔案所有者

PosixFileAttributeView: 修改檔案所有者,組所有者,通路權限, 同Linux的 chmod 指令

UserDefinedFileAttributeView: 自定義屬性

Path path2 = Paths.get("abc.txt");
        //基本屬性
        BasicFileAttributeView view = Files.getFileAttributeView(path2, BasicFileAttributeView.class);
        BasicFileAttributes attributes = view.readAttributes();
        //建立時間
        System.out.println(new Date(attributes.creationTime().toMillis()));
        //最後通路時間
        System.out.println(new Date(attributes.lastAccessTime().toMillis()));
        //最後修改時間
        System.out.println(new Date(attributes.lastModifiedTime().toMillis()));
        //檔案大小
        System.out.println(attributes.size());

        //檔案owner資訊
        FileOwnerAttributeView ownerAttributeView = Files.getFileAttributeView(path2, FileOwnerAttributeView.class);
        System.out.println(ownerAttributeView.getOwner());
        UserPrincipal user = FileSystems.getDefault()
                .getUserPrincipalLookupService().lookupPrincipalByName("zhangsan");
        ownerAttributeView.setOwner(user);

        //自定義屬性
        UserDefinedFileAttributeView defineView = Files.getFileAttributeView(path2, UserDefinedFileAttributeView.class);
        List<String> attNames = defineView.list();
        for(String name : attNames){
            ByteBuffer byteBuffer = ByteBuffer.allocate(defineView.size(name));
            defineView.read(name, byteBuffer);
            byteBuffer.flip();
            String value = Charset.defaultCharset().decode(byteBuffer).toString();
            System.out.println(name + " : " + value);
        }
        //添加自定義屬性
        defineView.write("作者", Charset.defaultCharset().encode("張三"));
        
        //檔案Dos屬性
        DosFileAttributeView dosView = Files.getFileAttributeView(path2, DosFileAttributeView.class);
        dosView.setHidden(true);
        dosView.setReadOnly(true);