java新输入/输出(nio)记录

来源:互联网 发布:广东干部教育培训网络 编辑:程序博客网 时间:2024/06/05 07:12

NIO中两个核心对象为Channel(通道)和Buffer(缓冲)

Buffer,ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer,MappedByteBuffer(ByteBuffer的子类)

实例化Buffer的方法(MappedByteBuffer除外):

ByteBuffer bb = ByteBuffer.allocate(capacity);


capacity为缓冲区容量。

对Buffer属性的一系列操作:

    public static void BufferTest() {        //创建普通的buffer        ByteBuffer bb = ByteBuffer.allocate(8);        //创建直接buffer和普通buffer对比是创建成本高,I/O操作较快        ByteBuffer bb2 = ByteBuffer.allocateDirect(8);        //buffer的三属性 关系为    容量cap>=界限lim>=位置pos        //容量        bb.capacity();        //界限        bb.limit();        //位置        bb.position();        /*         * 向普通buffer中存入元素,position随添加的元素而增涨初始为0         * pos=0 lim=8 cap=8         */        bb.put((byte) 'a');        bb.put((byte) 'b');        /*         * pos=2 lim=8 cap=8         * buffer为非空调用flip()为输出做准备          * 执行flip()后 limit指到有效长度position指到0的位置         */        bb.flip();        /*         * pos=0 lim=2 cap=8         * 输出数据结束后调用clear()为下次输入做准备          * 执行clear()后 limit指到capacity位置position指到0位置          */        bb.clear();        /*         * pos=0 lim=8 cap=8         * 如果再添加c元素到buffer 这时的position应该向后+1,并且覆盖掉原来的a         */        bb.put((byte) 'c');        //pos=1 lim=8 cap=8    }


Channel类

通过下面这个方法来了解:

    /**     * 传统的IO效率不高因为是依赖与字节来处理     * nio是依赖于映射内存区块来处理处理效率高     * 该方法典型的就是oc.write(mbbuffer);     * mbbuffer是Struts2Test.java的缓冲区块,这里是直接整块写出     * 传统的一般会类似:     * String str = "";     * while(str = buffer.readLine() != null) {     *     xxx.write(str);     * }     */    public static void channelTest() throws IOException {    /*     * Channel的实现类有:     * java.nio.channels包下     * DatagramChannel,FileChannel,SelectableChannel     * ServerSocketChannel,SocketChannel(支持tcp网络通信的管道)     * java.nio.channels.Pipe包下     * SinkChannel,SourceChannel(线程之间的通信管道)     */    //创建Channel实例 一般通过节点流创建Channel    File fileIn = new File("F:"+File.separator+"testSource"+File.separator+"Struts2Test.java");    File fileOut = new File("F:"+File.separator+"testSource"+File.separator+"nioTest.txt");    //创建节点流    FileInputStream fis = new FileInputStream(fileIn);    FileOutputStream fos = new FileOutputStream(fileOut);    //创建Channel    FileChannel ic = fis.getChannel();    FileChannel oc = fos.getChannel();    //Channel常用三方法map write read    //通过map方法把Channel包装成Buffer    MappedByteBuffer mbbuffer = ic.map(MapMode.READ_ONLY, 0, fileIn.length());    //Channel只能与buffer交互不能直接访问Channel的数据    oc.write(mbbuffer);    mbbuffer.clear();    ic.close();    oc.close();    }


 Channel的read类似write操作

  如果在noiTest.txt文件末尾追加Struts2Test.java的内容,可以在上面代码中

26行改为

//追加到文件末尾FileOutputStream fos = new FileOutputStream(fileOut, true);

32、33行之间加入

oc.position(fileOut.length());


结合Buffer的position属性不难推知这句代码的含义

 

编码解码就是ByteBuffer和CharBuffer之间的转换

Char转Byte为编码 反之为解码

下面代码简单说明了编码和解码:

public static void main(String[] args) throws CharacterCodingException {//Encode编码(Char->Byte) Decode解码(Byte->Char)//获取CharsetCharset cs = Charset.forName("GBK");//实例化普通BufferCharBuffer cb =CharBuffer.allocate(8);cb.put("牛");cb.put("羊");cb.put("马");cb.flip();//Charset自带编码ByteBuffer bb = cs.encode(cb);for(int i=0;i<bb.capacity();i++) {System.out.println(bb.get(i)+"\t");}System.out.println();//Charset自带解码CharBuffer cbNext = cs.decode(bb);System.out.println(cbNext);//编码 nioCharsetEncoder ce = cs.newEncoder();ByteBuffer niobb = ce.encode(cbNext);for(int i=0;i<niobb.capacity();i++) {System.out.println(niobb.get(i)+"\t");}//解码 nioCharsetDecoder cd = cs.newDecoder();CharBuffer niocb = cd.decode(niobb);System.out.println(niocb);}}


上面代码分别说明了两种编码和解码