• java基础:NIO之异步FileChannel和Charset(5)


    AsynchronousFileChannel

    在 Java 7 中,Java NIO 中添加了 AsynchronousFileChannel,也就是是异步地将数 据写入文件。

    创建 AsynchronousFileChannel

    通过静态方法 open()创建

            Path path = Paths.get("d:\1.txt");
            AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
    

    open()方法的第一个参数指向与 AsynchronousFileChannel 相关联文件的 Path 实例。

    第二个参数是一个或多个打开选项,它告诉 AsynchronousFileChannel 在文件上执行什么操作。在本例中,我们使用了 StandardOpenOption.READ 选项,表示该文件将被打开阅读。

    通过 Future 读取数据

    可以通过两种方式从 AsynchronousFileChannel 读取数据。第一种方式是调用返回 Future 的 read()方法

            Path path = Paths.get("d:\1.txt");
            AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
    
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            long position = 0;
            Future<Integer> operation = fileChannel.read(buffer, position);
    
            while(!operation.isDone());
    
            //返回读取到的字节数目
            System.out.println(operation.get());
    
            buffer.flip();
            byte[] data = new byte[buffer.limit()];
            buffer.get(data);
            System.out.println(new String(data));
            buffer.clear();
    

    上述代码:

    (1)创建了一个 AsynchronousFileChannel

    (2)创建一个 ByteBuffer,它被传递给 read()方法作为参数,以及一个 0 的位置。

    (3)在调用 read()之后,循环,直到返回的 isDone()方法返回 true。

    (4)读取操作完成后,数据读取到 ByteBuffer 中,然后打印到 System.out 中。

    通过 CompletionHandler 读取数据

    第二种方法是调用 read()方法,该方法将一个 CompletionHandler 作为参数

    示例:

            Path path = Paths.get("d:\1.txt");
            AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);;
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            long position = 0;
            fileChannel.read(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {
                //result 读取到的字节数目
                @Override
                public void completed(Integer result, ByteBuffer attachment) {
                    System.out.println("result = " + result);
                    attachment.flip();
                    byte[] data = new byte[attachment.limit()];
                    attachment.get(data);
                    System.out.println(new String(data));
                    attachment.clear();
                }
                @Override
                public void failed(Throwable exc, ByteBuffer attachment) {
                }
            });
    

    (1)读取操作完成,将调用 CompletionHandlercompleted()方法。

    (2)对于completed()方法的参数传递一个整数,它告诉我们读取了多少字节,以及传递给 read()方法的“附件”。“附件”是 read()方法的第三个参数。在本代码中,它是 ByteBuffer,数据也被读取。

    (3)如果读取操作失败,则将调用 CompletionHandlerfailed()方法。

    通过 Future和CompletionHandler 写入数据

    大部分代码与上面代码类似,这里不过多介绍。

    Future写入数据:open时指定StandardOpenOption.WRITE写操作

    AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
    Future<Integer> operation = fileChannel.write(buffer, position);
    buffer.clear();
    while(!operation.isDone());
    System.out.println("Write over");
    

    CompletionHandler 方式写入数据:

    fileChannel.write(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {
         @Override
         public void completed(Integer result, ByteBuffer attachment) {
         System.out.println("bytes written: " + result);
         }
         @Override
         public void failed(Throwable exc, ByteBuffer attachment) {
         System.out.println("Write failed");
         exc.printStackTrace();
         }
    });
    

    当写操作完成时,将会调用 CompletionHandlercompleted()方法。如果写失 败,则会调用 failed()方法。

    字符集(Charset)

    java 中使用 Charset 来表示字符集编码对象

    Charset 常用静态方法

    public static Charset forName(String charsetName)//通过编码类型获得 Charset 对象
    public static SortedMap<String,Charset> availableCharsets()//获得系统支持的所有编码方式
    public static Charset defaultCharset()//获得虚拟机默认的编码方式
    public static boolean isSupported(String charsetName)//判断是否支持该编码类型
    

    Charset 常用普通方法

    public final String name()//获得 Charset 对象的编码类型(String)
    public abstract CharsetEncoder newEncoder()//获得编码器对象
    public abstract CharsetDecoder newDecoder()//获得解码器对象
    

    示例:

            Charset charset = Charset.forName("UTF-8");
            //1.获取编码器
            CharsetEncoder charsetEncoder = charset.newEncoder();
            //2.获取解码器
            CharsetDecoder charsetDecoder = charset.newDecoder();
            //3.获取需要解码编码的数据
            CharBuffer charBuffer = CharBuffer.allocate(1024);
            charBuffer.put("字符集编码解码");
            charBuffer.flip();
            //4.编码
            ByteBuffer byteBuffer = charsetEncoder.encode(charBuffer);
            System.out.println("编码后:");
            for (int i=0; i<byteBuffer.limit(); i++) {
                System.out.println(byteBuffer.get());
            }
            //5.解码
            byteBuffer.flip();
            CharBuffer charBuffer1 = charsetDecoder.decode(byteBuffer);
            System.out.println("解码后:");
            System.out.println(charBuffer1.toString());
            System.out.println("指定其他格式解码:");
            Charset charset1 = Charset.forName("GBK");
            byteBuffer.flip();
            CharBuffer charBuffer2 = charset1.decode(byteBuffer);
            System.out.println(charBuffer2.toString());
            //6.获取 Charset 所支持的字符编码
            Map<String ,Charset> map = Charset.availableCharsets();
            Set<Map.Entry<String,Charset>> set = map.entrySet();
            for (Map.Entry<String,Charset> entry: set) {
                System.out.println(entry.getKey() + "=" + entry.getValue().toString());
            }
    

    运行结果:

    image-20211103145134840

  • 相关阅读:
    坐标系的冷知识2
    坐标系的冷知识
    XMPP即时通讯(代码实现)
    约束问题
    实现ios屏幕的横竖屏自适应
    3D Touch ? 木有6s,也阔以玩!!!
    Autolayout
    Xcode7免证书真机调试
    微信支付
    二维码扫描
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/15503589.html
Copyright © 2020-2023  润新知