java IO细解

java IO问题是面试时经常关心的问题。java IO的发展从传统的IO到NIO再到AIO。

一、什么是I/O

IO即是指输入源及输出目的地。IO流可能会是不同种类的源和目的地,例如可以是磁盘文件、其它程序、一些设备、或者是内存数组等等。流可支持多种数据,包括简单的字节、基本数据类型、字符、甚至是对象。一些流仅仅是用于传递数据,而一些流是使用有效的方式来操作或转换数据。但不管这些流的内部是如何工作的,程序使用的流都可以归纳为这样简单的模型:流就是数据队列。程序从流的源一条一条的读取数据,或者一条一条的写数据到目的地。

二、字节流

一个字节是8位二进制数。字节流顾名思义,是程序每次都是对一个字节进行输出输出。字节流的类都是根源于InputStream及OutputStream。

简单的例子:

  FileInputStream in = null;
  FileOutputStream out = null;

  try {
        in = new FileInputStream("in.txt");
        out = new FileOutputStream("out.txt");
        int c;

        while ((c = in.read()) != -1) {
            out.write(c);
        }
  } finally {
        if (in != null) {
            in.close();
        }
        if (out != null) {
            out.close();
        }
  }

字节流是原始的IO处理方式。它实际上是一种低级的IO方式,它花费时间的地方主要在循环读取一条数据或写一条数据。我们在使用时要避免这种方式。之所以提到字节流,是因为其他所有的流都是在字节流的基础上进行设计的。

三、字符流

java平台存储字符值通常是使用unicode编码。字符流IO会自动将字符从本地字符集转换成unicode编码。通常在使用字符流类时,要考虑字符集国际化问题,不然字符流在内部转化时就会出现问题。通常我们会统一本地字符集和java平台的字符集。所有的字符流的类都是基于Reader和Writer的。

简单例子:

        FileReader inputStream = null;
        FileWriter outputStream = null;

        try {
            inputStream = new FileReader("in.txt");
            outputStream = new FileWriter("out.txt");

            int c;
            while ((c = inputStream.read()) != -1) {
                outputStream.write(c);
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        }

我们通常用字符流包装字节流,连接字节流与字符流的桥梁是InputStreamReader和OutputStreamWriter。字符流也可以一次读取一整行数据。例如:

        BufferedReader inputStream = null;
        PrintWriter outputStream = null;

        try {
            inputStream = new BufferedReader(new FileReader("in.txt"));
            outputStream = new PrintWriter(new FileWriter("out.txt"));

            String l;
            while ((l = inputStream.readLine()) != null) {
                outputStream.println(l);
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        }

字符流的输入文本的行结束符通常是\r或\n,但是也可以自定行结束符,这个可以使用Scanner类来包装字符流。

四、缓冲流

上面的字节流和字符流的每次操作都是由操作系统来执行,这将导致频繁的磁盘IO及网络IO。为了减少这种IO压力,java提供了带有缓冲区的IO流。缓冲流提供一个内存缓冲区,缓冲区有一定大小,读操作是调用native方法将数据读入缓冲区,当且仅当缓冲区是空的时候才会触发,然后缓冲流从缓冲区读数据。

每一种输出流都有flush方法,尽管每个输出流都可以调用flush方法,但是如果不是缓存流,则flush方法其实是不起作用的。

五、数据流

数据流提供对于基本数据类型及String类型数据的读写API。数据流读写的是二进制文件,它的数据类似一条条的记录,每条记录可以包含基本数据类型或String类型。所有的数据流都实现了DataInput和DataOutput接口。

六、对象流

对象流顾名思义,即可以对一个object进行IO操作。一般的标准的class只要实现了Serializable标记接口,都可以序列化自己。所有的对象流都实现了ObjectInput和ObjectOutput接口,这两个接口也是DataInput和DataOutput接口的子接口。

七、NIO

NIO是jdk1.4后出现的特性,它设计的目的是为了克服之前的java.net下的API的局限性。NIO主要应用于网络编程。NIO将IO操作转移到底层的操作系统来处理,这大大提升了效率。jdk1.4后的java.io包已经以NIO为基础,一些IO流也提供以块的方式读写数据。

NIO API的核心是:

  1. Buffers,数据的缓冲区,缓冲区就是数据的容器,任何读取或写入操作首先就需要将数据读入或写入缓冲区;
  2. Charsets,字符集,包括关联的编码和解码器,用于字节到unicode字符之间的转换。
  3. Channels,各种管道,它让相连接的各个实体之间有效的执行IO操作,任何操作都需要借助管道进行;
  4. Selectors,选择器包括选择密钥,与可供选择的管道一起组成复杂的、非阻塞的IO。非阻塞IO也是NIO的真正含义。

Buffer是一个基本数据类型的数据容器。它是线性的、有限的基本类型的元素队列。buffer的基本属性是capacity(容量)、limit(限制)、position(位置)。capacity是buffer能够存放的元素的数量,capacity的值不会是负数,也不会被更改。limit是指buffer中不应该被读取或写入的第一个元素的索引,limit的值也不会是负数、而且不会大于容量。position是buffer中下一个将被读取或写入的元素的索引,position不能为负数,且不能大于他的限制值。

Channel类似传统IO中的流。NIO中所有IO操作都是通过channel进行,它与流不同的是流是单向的,即流必须是输出流或输入流中的一种,流要么只能写要么只能读,而管道是双向的,管道可以同时进行读写。

NIO不仅是引入了按块处理IO的设计思想,更重要的是在于解决了传统网络IO编程中服务线程问题,传统网络IO是一个客户端的连接对应一个服务端的线程,这种1对1的模式将会消耗大量线程资源,而NIO可以一个线程处理多个客户端的消息,它的核心类就是Selector。

八、NIO.2

NIO.2是java7对NIO的完善和补充。NIO.2加入了异步IO的思想,jdk1.4的NIO是同步IO,即每次IO操作都需要等待操作完成程序才会往下继续进行,而NIO.2的IO操作是异步进行的,即使这次IO操作还没有完成,程序也不会等待,将继续往下进行。为了监控操作的结果和状态,NIO.2的API提供了一个Future类,一些异步执行的操作返回值都是Future,这个类提供了一些API,用于获取执行结果或状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值