java核心学习(十八) javaNIO框架---“块”模型的IO

Posted The_shy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java核心学习(十八) javaNIO框架---“块”模型的IO相关的知识,希望对你有一定的参考价值。

一、java新IO概述

  javaIO中的输入流和输出流都是通过字节的移动来处理的,面向流的输入输出系统一次只能处理一个字节,因此效率不高,而且传统的输入输出流是阻塞试的,也就是说当无法读到数据时,当前线程会被阻塞直到读取到有效数据才会继续运行。

  java1.4之后提供了一系列改进的输入输出类与方法,并且以NIO为基础改写了java.io包中的类,新增了满足NIO的功能。

  NIO采用内存映射文件的方式,java.nio中主要的包有:

    java.nio ,主要包含于Buffer相关的类;

    java.nio.charset,主要包含字符集相关的类;

    java.nio.channels,主要包含Channel和Selector相关的类;

    java.nio.channels.spi,主要包含与Channel相关的服务提供者编程接口;

    java.nio.charset.spi,包含与字符集相关的服务提供者编程接口。

二、Buffer抽象类

  其子类有ByteBuffer(最常用)、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer,这些类没有构造器,获取buffer对象使用如下静态方法:static XxxBuffer allocate(int capacity)。

  Buffer的几个位置属性:

  

  相应的两个方法:clear(),let limit = capacity and position = 0,这相当于是为再次将数据写入Buffer做好准备,

          flip(),let limit = position and position = 0 ,这相当于是为从Buffer中取出数据做好准备。

package NIOTest;

import java.nio.CharBuffer;

public class BufferTest {
    public static void main(String[] args)
    {
        CharBuffer buffer = CharBuffer.allocate(8);
        System.out.println("capacity:" +buffer.capacity());
        System.out.println("limit:" +buffer.limit());
        System.out.println("position" + buffer.position());

        buffer.put(\'a\');
        buffer.put(\'b\');
        buffer.put(\'c\');
        System.out.println("加入三个元素后,position = " + buffer.position());
        buffer.flip();
        System.out.println("执行flip()后,limit = " + buffer.limit());
        System.out.println("position = " + buffer.position());
        //去除第一个元素
        System.out.println("第一个元素(position=0):" + buffer.get());
        System.out.println("取出第一个元素后,position = " + buffer.position());
        //调用clear方法
        buffer.clear();
        System.out.println("执行clear()后,limit = " + buffer.limit());
        System.out.println("执行clear()后,position = " + buffer.position());
        System.out.println("执行clear()后,buffer内容并没有被清除:" + "第三个元素为:"+ buffer.get(2));
        System.out.println("执行绝对读取后,position = " + buffer.position());
    }
}

  上面代码尝试了一下Buffer的使用,输出为下

capacity:8
limit:8
position0
加入三个元素后,position = 3
执行flip()后,limit = 3
position = 0
第一个元素(position=0):a
取出第一个元素后,position = 1
执行clear()后,limit = 8
执行clear()后,position = 0
执行clear()后,buffer内容并没有被清除:第三个元素为:c
执行绝对读取后,position = 0

  上面程序使用的buffer是heapbuffer,每个heapbuffer在新建时都会创建一个对应的directbuffer,直接buffer的读取效率高但是创建成本也高,具体buffer1的工作方式不在这里深究= =,因为深究了没有实际应用也会忘记。。

 

三、 Channel接口

  Channel用于与Buffer交互,实现数据的IO。

  java为Channel接口提供了DatagramChannel(支持UDP网络通信)、FileChannel(文件读写)、Pipe.SinkChannel和Pipe.SourceChannel(支持线程间通信的管道)、SelectableChannel(可选择阻塞与非阻塞的channel)、ServerSocketChannel和SocketChannel(支持TCP网络通信)等等。

  Channel通过传统的流节点来返回对应的Channel,常用的方法有map()、read()、write(),下面来试一试

  

package NIOTest;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

public class FileChannelTest {
    public static void main(String[] args) {
        File f = new File("./src/main/java/NIOTest/FileChannelTest.java");
        try (
                FileChannel inChannnel = new FileInputStream(f).getChannel();
                FileChannel outChannel = new FileOutputStream("a.txt").getChannel();

        ) {
            MappedByteBuffer buffer = inChannnel.map(FileChannel.MapMode.READ_ONLY, 0, f.length());
            Charset charset = Charset.forName("GBK");
            outChannel.write(buffer);
            buffer.clear();
            CharsetDecoder decoder = charset.newDecoder();
            CharBuffer charBuffer = decoder.decode(buffer);
            System.out.println(charBuffer);


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

  下面代码每次运行都会讲a.txt文件的内容复制一份并将全部内容追加到该文件的后面

package NIOTest;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class RandomFileChannelTest {
    public static  void mian (String[] args){
        File f= new File("a.txt");
        try(
                RandomAccessFile raf = new RandomAccessFile(f,"rw");
                FileChannel randomChannel = raf.getChannel();
                ){
            ByteBuffer buffer = randomChannel.map(FileChannel.MapMode.READ_ONLY,0,f.length());
       //这里移动的是channel的position,可以在任意位置将数据写入channel。 randomChannel.position(f.length()); randomChannel.write(buffer); }
catch (IOException ioe){ ioe.printStackTrace(); } } }

 

四、Charset类

  字符集类主要用于文本格式数据编码与解码,具体用法在 三 中的第一个例子有所展示。

 

以上是关于java核心学习(十八) javaNIO框架---“块”模型的IO的主要内容,如果未能解决你的问题,请参考以下文章

Java框架spring学习笔记(十八):事务操作

1.28 Java学习系列(二十八)UML建模的理解和图形整理

Java NIO三组件——Selecotr/Channel实现原理解析

Java NIO三组件——Selecotr/Channel实现原理解析

JAVA框架技术之十八节springboot课件上手教程

JAVA框架技术之十八节springboot课件上手教程