当前位置:网站首页>01-NIO基础之ByteBuffer和FileChannel

01-NIO基础之ByteBuffer和FileChannel

2022-04-23 14:05:00 想到的名字都被人用了

一、channel和buffer

channel是用户通信的通道,buffer是缓冲区,再从channel读取数据之前,我们要先将数据读取到buffer中,再从buffer中取出来。再向channel写入数据之前,也是将数据写入buffer中,channel再从buffer中拿去数据。

常见的channel

  • FileChannel
  • SocketChannel
  • ServerSocketChannel

Buffer的种类有很多,最常用的便是ByteBuffer了

二、ByteBuffer

ByteBuffer有两种模式:读模式和写模式
写模式
在这里插入图片描述
在这里插入图片描述

读模式

在这里插入图片描述
在这里插入图片描述

写模式---->读模式: flip()
读模式---->写模式:clear()、compact()

(一) compact和clear的区别

clear
在这里插入图片描述
compact
在这里插入图片描述

(二) ByteBuffer常用方法

读取方法:

  • get():每读取一次position会往前移动一位
  • get(int i):读取第i个字节,position不会移动

写入方法:

  • write(Byte b)、write(Byte[])、write(ByteBuffer)

分配空间

  • allocate()

重置position

  • rewind:重置position为0并清楚mask
  • mask和reset
    mask用来标记位置,reset会将position置为mask的位置
  • position(int newPosition):设置新的位置

正确使用buffer的例子

public static void main(String[] args) {
        try{
            FileChannel channel = new RandomAccessFile("D:\\test.txt", "rw").getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(4);
            while(channel.read(buffer) != -1){
                buffer.flip();
                while(buffer.hasRemaining()){
                    log.debug("{}", (char)buffer.get());
                }
                buffer.clear();
            }
        }catch (Exception e){
            System.out.println(e.fillInStackTrace());
        }
    }

半包、粘包

 public static ByteBuffer split(ByteBuffer source){

        //切换成读模式
        source.flip();
        int limit = source.limit();
        for(int i=0; i<limit;i++){
            //get(i)不会移动position但get()会
            if(source.get(i) == '\n'){
               int len = i - source.position() + 1;
                ByteBuffer target = ByteBuffer.allocate(len);
                for(int j = source.position(); j < len; j++){
                    target.put(source.get());
                }
                target.flip();
                ByteBufferUtil.debugAll(target);
                source.compact();
                return target;
            }
        }

        return null;
    }

三、FileChannel、Path、Files

(一) Path

Path source = Paths.get("1.txt"); // 相对路径 使用 user.dir 环境变量来定位 1.txt

Path source = Paths.get("d:\\1.txt"); // 绝对路径 代表了  d:\1.txt

Path source = Paths.get("d:/1.txt"); // 绝对路径 同样代表了  d:\1.txt

Path projects = Paths.get("d:\\data", "projects"); // 代表了  d:\data\projects

Path path = Paths.get("d:\\data\\projects\\a\\..\\b");
System.out.println(path);
System.out.println(path.normalize()); // 正常化路径
输出:
d:\data\projects\a\..\b
d:\data\projects\b

(二) Files

  • 检查文件是否存在:exists(path)
  • 创建目录:createDirectory(path)、createDirectories(path)
  • 拷贝文件:Files.copy(source, target);
  • 删除文件:Files.delete(target);

遍历目录

public static void main(String[] args) throws IOException {
    Path path = Paths.get("C:\\Program Files\\Java\\jdk1.8.0_91");
    AtomicInteger dirCount = new AtomicInteger();
    AtomicInteger fileCount = new AtomicInteger();
    Files.walkFileTree(path, new SimpleFileVisitor<Path>(){
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) 
            throws IOException {
            System.out.println(dir);
            dirCount.incrementAndGet();
            return super.preVisitDirectory(dir, attrs);
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 
            throws IOException {
            System.out.println(file);
            fileCount.incrementAndGet();
            return super.visitFile(file, attrs);
        }
    });
    System.out.println(dirCount); // 133
    System.out.println(fileCount); // 1479
}

删除目录

Path path = Paths.get("d:\\a");
Files.walkFileTree(path, new SimpleFileVisitor<Path>(){
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 
        throws IOException {
        Files.delete(file);
        return super.visitFile(file, attrs);
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) 
        throws IOException {
        Files.delete(dir);
        return super.postVisitDirectory(dir, exc);
    }
});

版权声明
本文为[想到的名字都被人用了]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_42861526/article/details/124236184