码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2017-09-18 14:52:44      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:sele   bsp   imp   source   提供者   dom   线程间通信   getc   span   

一、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

标签:sele   bsp   imp   source   提供者   dom   线程间通信   getc   span   

原文地址:http://www.cnblogs.com/Theshy/p/7535745.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!