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());
        }

运行结果:

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

上一篇:No converter for [class xxx] Content-Type ‘appliction/octet-stream;charset=UTF-8‘ 的解决办法


下一篇:微信公众号模板消息推送,中文乱码