Java-第十七部分-NIO-Pipe、FileLock、Path和Files

278 阅读2分钟

NIO全文

Pipe

  • 两个线程之间的单向数据连接,从source通道读取和sink通道写入
//获取通道
Pipe pipe = Pipe.open();
//写入
Pipe.SinkChannel sink = pipe.sink();
ByteBuffer bbSink = ByteBuffer.allocate(1024);
bbSink.put("PipeDemo".getBytes());
bbSink.flip();
sink.write(bbSink);
//读取
Pipe.SourceChannel source = pipe.source();
ByteBuffer bbSource = ByteBuffer.allocate(1024);
int len = source.read(bbSource);
System.out.println(new String(bbSource.array(), 0, len));
source.close();
sink.close();

两个线程的案例

Pipe pipe = Pipe.open();
new Thread(() -> {
    Pipe.SourceChannel source = pipe.source();
    ByteBuffer bb = ByteBuffer.allocate(1024);
    bb.clear();
    try {
        //阻塞在这里,等待sink端写入
        int len = source.read(bb);
        if (len != -1) {
            bb.flip();
            System.out.println(new String(bb.array(), 0, len));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + " - finished");
},"B").start();
new Thread(() -> {
    Pipe.SinkChannel sink = pipe.sink();
    ByteBuffer bb = ByteBuffer.allocate(1024);
    bb.put(Thread.currentThread().getName().getBytes());
    bb.flip();
    try {
        TimeUnit.SECONDS.sleep(1);
        sink.write(bb);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            sink.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    System.out.println(Thread.currentThread().getName() + " - finished");
}, "A").start();

FileLock

  • 文件锁,同一个时间,只能有一个程序修改此文件
  • 进程级别,解决多个进程并发访问、修改同一个文件的问题;同一个进程内的多个线程,可以同时访问,修改文件
  • 进程对文件不能重复加锁
  • 锁释放
  1. 调用release()
  2. 关闭对应的FileChannel对象
  3. 当前JVM退出
  • 分类
  1. 排它锁,独占锁,对文件加锁后,其他进程不能读写此文件,直到该进程释放锁
  2. 共享锁,其他进程只能读此文件
  • lock与tyrlock
  1. lock,阻塞式的,如果未获取到文件锁,会一直阻塞当前线程
  2. 非阻塞式,尝试获取文件锁,成功返回锁对象,失败返回null
  • 实际上是一种设计思想,只有获取锁之后才能进行处理
String pathName = "/Users/mzx/Desktop/java/nio/test4.txt";
String input = Thread.currentThread().getName();
Path path = Paths.get(pathName);
ByteBuffer bb = ByteBuffer.allocate(1024);
FileChannel fc = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE);
//加锁,如果是独占锁,其他进程不能获得锁;如果是共享锁,就可以获得
FileLock lock = fc.lock(0, Long.MAX_VALUE, true);
fc.position(fc.size() - 1);
fc.write(ByteBuffer.wrap(input.getBytes()));
//是否是共享锁
System.out.println(lock.isShared());
//读
fc.position(0);
int len = fc.read(bb);
System.out.println(len);
bb.flip();
System.out.println(new String(bb.array(), 0, len));
TimeUnit.SECONDS.sleep(300);

Path

  • 获取
String pathName = "/Users/mzx/Desktop/java/nio/test4.txt";
//创建决定路径
Path path = Paths.get(pathName);
System.out.println(path);
//创建相对路径,路径拼接
Path path1 = Paths.get("/Users/mzx/Desktop/java", "nio/test4.txt");
System.out.println(path1);

//sout
/Users/mzx/Desktop/java/nio/test4.txt
/Users/mzx/Desktop/java/nio/test4.txt
  • 标准化
//..代表Desktop的上一层
String pathName1 = "/Users/mzx/Desktop/../java/nio/test4.txt";
Path path2 = Paths.get(pathName1);
System.out.println(path2);
Path path3 = path2.normalize();
System.out.println(path3);

//sout
/Users/mzx/Desktop/../java/nio/test4.txt
/Users/mzx/java/nio/test4.txt

Files

  • 目录
//新建目录,目录存在或者不存在父目录,抛出异常;
Path path = Paths.get("/Users/mzx/Desktop/java/nio/test");
Files.createDirectory(path);
//递归创建
Files.createDirectories(Paths.get("/Users/mzx/Desktop/java/nio/test1/test"));
  • 文件复制
Path from = Paths.get("/Users/mzx/Desktop/java/nio/test1.txt");
Path to = Paths.get("/Users/mzx/Desktop/java/nio/test/test10.txt");
Files.copy(from,to);
//覆盖
Files.copy(from,to, StandardCopyOption.REPLACE_EXISTING);
  • 移动和重命名
Path from = Paths.get("/Users/mzx/Desktop/java/nio/test/test101.txt");
Path to = Paths.get("/Users/mzx/Desktop/java/nio/test/test10.txt");
//可以进行重命名,文件名与to相同,会异常,可以进行覆盖
Files.move(from, to, StandardCopyOption.REPLACE_EXISTING);
  • 删除
Path path = Paths.get("/Users/mzx/Desktop/java/nio/test/test10.txt");
Files.delete(path);
Files.deleteIfExists(path);
  • 文件目录遍历
Path root = Paths.get("/Users/mzx/Desktop/java/nio");
//找文件
String fileToFind = File.separator + "test4.txt";
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        String fileString = file.toAbsolutePath().toString();
        if (fileString.endsWith(fileToFind)) {
            System.out.println("success - " + file.toAbsolutePath());
            return FileVisitResult.TERMINATE;
        }
        System.out.println(file.toAbsolutePath());
        return FileVisitResult.CONTINUE;
    }
});