NIO2

目录

一、重要类

1、Path类

2、Files工具类、Paths工具类

3、FileVisitor遍历目录和文件

4、使用WatchService监控文件变化

5、访问文件属性的一些高级方式


NIO2是在NIO的基础上进行的扩展。Java 7 对原有的NIO进行了改进:

  • 提供了全面的文件IO和文件系统访问支持:表现为Java 7新增的java.nio.file包及其各个子包
  • 基于异步Channel的IO : 在java.nio.channels包下新增了多个以Asynchronous开头的Channel接口和类

Java 8进一步增强了Files工具类的用法,允许开发者使用Stream API来操作文件目录和文件内容。

 

一、重要类

NIO2或者说NIO中的核心类:Path、 Paths、Files

对应早期Java中的File类,File类是用来访问文件系统,但是功能有限(尽管我还用的挺舒服的),它不能利用特定文件系统的特性,其提供方法的访问性能也不高,NIO2为了弥补这种不足,引入了Path接口,Path代表一个平台无关的平台路径。

另外Files、Paths是两个工具类,包含大量的静态方法。

1、Path类

 对应原有的java.io.File类

使用示例:

import java.nio.file.Path;
import java.nio.file.Paths;

public class PathTest {
    public static void main(String[] args) {
        Path path = Paths.get(".");
        System.out.println("path路径:" + path);  // 输出: path路径:.
        System.out.println("path里包含的路径数量:" + path.getNameCount());  // 结果为1
        System.out.println("path的根路径:" + path.getRoot()); // 结果为null
        System.out.println("path的父路径:" + path.getParent()); // 输出: path的父路径:null

        Path absolutePath = path.toAbsolutePath();
        System.out.println("path的绝对路径:" + absolutePath); // 输出: path的绝对路径:/Users/qinwenjing/Documents/Projects/Test/.
        System.out.println("path的绝对路径名称:" + absolutePath.getFileName()); // 输出: path的绝对路径名称:.
        System.out.println("path的绝对路径的根路径:" + absolutePath.getRoot()); // 输出: path的绝对路径的根路径:/
        System.out.println("path的绝对路径数量:" + absolutePath.getNameCount());
        System.out.println("path的绝对路径下标为3的路径名称:" + absolutePath.getName(3));
        System.out.println("path的绝对路径的父路径:" + absolutePath.getParent()); // path的绝对路径的父路径:/Users/qinwenjing/Documents/Projects/Test

        // 以多个string构造Path
        Path path1 = Paths.get("g:", "publish", "codes");
        System.out.println(path1);
    }
}

2、Files工具类、Paths工具类

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class FilesTest {
    public static void main(String[] args) {
        try {
            Path path = Paths.get("/Users/qinwenjing/Documents/Projects/Test/test2.txt");
            // 复制文件
            Files.copy(path, new FileOutputStream("b.txt"));
            // 判断是否是隐藏文件
            System.out.println(Files.isHidden(path));
            // 输出文件的大小
            System.out.println(Files.size(path));

            // 一次性读取文件中所有的行
            List<String> linesList = Files.readAllLines(path);
            System.out.println(linesList);

            // 直接将多个字符串写入到指定的文件
            Files.write(Paths.get("/Users/qinwenjing/Documents/Projects/Test/d.txt"), linesList, Charset.forName
                    ("utf-8"));

            // 列出当前目录下所有的文件和子目录
            Files.list(Paths.get(".")).forEach(p -> System.out.println(p));

            System.out.println("--------读取文件内容---------");
            Files.lines(path, Charset.forName("utf-8")).forEach(line -> System.out.println(line));

            FileStore fileStore = Files.getFileStore(path);
            System.out.println("共用空间:" + fileStore.getTotalSpace());
            System.out.println("可用空间:" + fileStore.getUsableSpace());
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

3、FileVisitor遍历目录和文件

FileVisitor是一个接口,默认实现类SimpleFileVisitor。FileVisitor中的方法:

1、访问目录前触发的方法

FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)

2、访问文件时触发的方法

FileVisitResult visitFile(T file, BasicFileAttributes attrs)

3、访问文件失败时触发的方法

FileVisitResult visitFileFailed(T file, IOException exc)

4、访问目录后触发的方法

FileVisitResult postVisitDirectory(T dir, IOException exc)
 

其返回值是 FileVisitResult, FileVisitResult是个枚举:

public enum FileVisitResult {
    /**
 * Continue. When returned from a {@link FileVisitor#preVisitDirectory
 * preVisitDirectory} method then the entries in the directory should also
 * be visited.
 */
 CONTINUE,
    /**
 * Terminate.
 */
 TERMINATE,
    /**
 * Continue without visiting the entries in this directory. This result
 * is only meaningful when returned from the {@link
 * FileVisitor#preVisitDirectory preVisitDirectory} method; otherwise
 * this result type is the same as returning {@link #CONTINUE}.
 */
 SKIP_SUBTREE,
    /**
 * Continue without visiting the <em>siblings</em> of this file or directory.
 * If returned from the {@link FileVisitor#preVisitDirectory
 * preVisitDirectory} method then the entries in the directory are also
 * skipped and the {@link FileVisitor#postVisitDirectory postVisitDirectory}
 * method is not invoked.
 */
 SKIP_SIBLINGS;
}


4、使用WatchService监控文件变化

考虑这样一个需求:需要监控文件的变化,那该怎样做呢?常规的做法就是启动一个线程(定时任务),每隔一段时间去『遍历』一次指定的目录的文件,如果遍历的结果和上次不同,则认为文件发生了变化。但是有没有更好的方式来实现呢?

NIO2利用WatchService类提供了如下一个监听文件系统的变化的方法:

示例:

import java.io.IOException;
import java.nio.file.FileSystems;
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;

/**
 * WatchService代表一个文件系统监听服务,负责监听path表示的路径下文件变化,
 * 一旦使用了register()方法注册之后,接下里就可以调用watchService的方法来获取被监听的文件变化事件
 */
public class WatchServiceTest {
    public static void main(String[] args) {
        try {
            WatchService watchService = FileSystems.getDefault().newWatchService();
            Paths.get("/Users/qinwenjing/Documents/Projects/Test/src/main/java")
                    .register(watchService,
                            StandardWatchEventKinds.ENTRY_CREATE,
                            StandardWatchEventKinds.ENTRY_DELETE,
                            StandardWatchEventKinds.ENTRY_MODIFY);

            while (true) {
                // 获取下一个文件变化事件 (获取下一个WatchKey),如果没有发生就等待
                WatchKey key = watchService.take();
                // 获取下一个文件变化事件(获取下一个WatchKey),没有的话就返回null
                // WatchKey key = watchService.poll();
                System.out.println("拿到watchKey....");
                for (WatchEvent event : key.pollEvents()) {
                    System.out.println(event.context() + " 文件发生了" + event.kind() + "事件!");
                }
                // 重设WatchKey
                boolean valid = key.reset();
                if (!valid) {
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

5、访问文件属性的一些高级方式

早期的File类可以访问一些简单的文件属性,比如文件大小、修改时间、文件是否隐藏、是文件还是目录等。如果需要获取或修改更多的文件属性,这是可以利用Java 7的NIO2在java.nio.file.attribute包下提供的大量工具类。

示例:

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.attribute.FileOwnerAttributeView;
import java.nio.file.attribute.UserDefinedFileAttributeView;
import java.nio.file.attribute.UserPrincipal;
import java.util.Date;
import java.util.List;

public class AttributeViewTest {
    public static void main(String[] args) {
        Path testPath = Paths.get("/Users/qinwenjing/Documents/Projects/Test/src/main/java/IO/NIO2/AttributeViewTest"
                + ".java");
        File file = new File("/Users/qinwenjing/Documents/Projects/Test/src/main/java/IO/NIO2/AttributeViewTest"
                + ".java");

        try {
            // 1、获取访问 基本属性 的BasicFileAttributeView
            BasicFileAttributeView baseView = Files.getFileAttributeView(testPath, BasicFileAttributeView.class);
            // 获取访问基本属性的BasicFileAttributes
            BasicFileAttributes basicFileAttributes = baseView.readAttributes();
            System.out.println("创建时间   :" + basicFileAttributes.creationTime().toMillis());
            System.out.println("最后访问时间:" + basicFileAttributes.lastAccessTime().toMillis());
            System.out.println("最后修改时间:" + new Date(basicFileAttributes.lastModifiedTime().toMillis()));

            // 2、获取访问 文件属主信息 的FileOwnerAttributeView
            FileOwnerAttributeView ownerView = Files.getFileAttributeView(testPath,
                    FileOwnerAttributeView.class);
            // 获取文件所属的用户
            System.out.println(ownerView.getOwner());

            // 获取系统中qinwenjing对应的用户
            UserPrincipal user = FileSystems.getDefault().getUserPrincipalLookupService().lookupPrincipalByName
                    ("qinwenjing");
            // 修改用户
            ownerView.setOwner(user);

            // 3、获取访问Dos属性的DosFileAttributeView
            DosFileAttributeView dosView = Files.getFileAttributeView(testPath, DosFileAttributeView.class);
            // 将文件设置为隐藏、只读
            dosView.setHidden(true);
            dosView.setReadOnly(true);


            // 4、获取访问自定义属性的UserDefinedFileAttributeView(可能为null)
            UserDefinedFileAttributeView userView = Files.getFileAttributeView(testPath, UserDefinedFileAttributeView
                    .class);
            List<String> attributes = userView.list();
            for (String name : attributes) {
                ByteBuffer buf = ByteBuffer.allocate(userView.size(name));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值