java之IO流总结

java之IO流总结


1.什么是IO流?

        Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。
        Java.io是大多数面向数据流的输入/输出类的主要软件包。此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO。
        IO流的好处是简单易用,缺点是效率较低。块IO效率很高,但编程比较复杂。
Java IO模型 :
        Java的IO模型设计非常优秀,它使用Decorator模式,按功能划分Stream,您可以动态装配这些Stream,以便获得您需要的功能。例如,您需要一个具有缓冲的文件输入流,则应当组合使用FileInputStream和BufferedInputStream。


2. 数据流的基本含义

1)数据流
        一组有序,有起点和终点的字节的数据序列。包括输入流和输出流。
这里写图片描述
2)输入流(Input Stream)
        程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道。
这里写图片描述

3)输出流(Output Stream)
        程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络…)的通信通道。
这里写图片描述


采用数据流的目的就是使得输出输入独立于设备。

Input Stream不关心数据源来自何种设备(键盘,文件,网络)
Output Stream不关心数据的目的是何种设备(键盘,文件,网络)
4 数据流分类:
流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:
1) 字节流:数据流中最小的数据单元是字节
2) 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。


3. java.io层次体系结构

用一张结构图来说明:
这里写图片描述

  1. File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。
  2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
  3. OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。
         Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。
  4. Reader(文件格式操作):抽象类,基于字符的输入操作。
  5. Writer(文件格式操作):抽象类,基于字符的输出操作。
  6. RandomAccessFile(随机文件操作):它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。


基本数据流的I/O

输入/输出字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter


4. InputStream与Reader,OutputStream与Writer的区别

InputStream:
InputStream 此抽象类是表示字节输入流的所有类的超类

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,否则可能接受平台默认的字符集。

每次调用 InputStreamReader 中的一个 read() 方法都会导致从基础输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从基础流读取更多的字节,使其超过满足当前读取操作所需的字节。

OutputStream:
一个是字符流输出,一个是字节流输出
从本质上讲,wirter/reader和inputstream/outputstream的最大区别在于encode和decode.
inputstream/outputstream 直接对byte[]进行操作,不会更改任何信息,原原本本的反应数据内容.
writer/reader在操作时会进行decode/encode. 它会根据你的系统属性file.encoding来decode数据.比如你从文件中读取一行,用reader.readLine()返回的string是经过decode的数据.如果你的文件的encoding不等于你的file.encoding的值,就会产生编码错误.


5. I/O的Buffer及其处理

字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流。
问题引入:
缓冲流为什么比普通的文件字节流效率高?
不带缓冲的操作,每读一个字节就要写入一个字节。
由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。
带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。
等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多!
这就是两者的区别。
大概过程:
没有缓存区,那么每read一次,就会发送一次IO操作;
有缓存区,第一次read时,会一下读取x个字节放入缓存区,然后后续的read都会从缓存中读取,当read到缓存区末尾时,会再次读取x个字节放入缓存区。
很明显,
第二种方式,会减少IO操作,效率更高,缺点就是,内存占用的多。
java输入输出流
采用了多层封装的方式进行设计最底层 InputStream和OutputStream 基于字节流,没有缓存机制,一般用BufferInputStream和BufferOutputStream进行封装后使用。

BufferInputStream的read方法是阻塞线程的,BufferInputStream.read(buf) 会将输入流内的全部读入buf之后才返回。

BufferOutputStream.write(buf);会将buf中的内容输出到输出流,但是记得要flush;
还有个比较好用的PrintStream 和PrintWriter相似 可以自动刷新 只不过是对于字节流而言。
字节流一般用于传送二进制文件之类 至于字符流常常用reader进行包装后使用。

最常用的有BufferInputStreamReader和PrintWrinter ,BufferInputStreamReader的readline方法很实用 遇到\r\d会自动flush。

PrintWrinter 只要在构造函数中设置了刷新属性为true则其println方法可以自动刷新不用flush。

FilterInputStream和FilterOutputStream:过滤流,buffer流和data流均继承于此。
对于buffer流,只有缓冲区满时,才会将数据真正到输出流,但可以使用flush()方法人为的将尚未填满的缓冲区中的数据送出.

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页