Java - IO(Input Output)流

Posted Lam

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java - IO(Input Output)流相关的知识,希望对你有一定的参考价值。

技术图片

一、流的概念和作用

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。

即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

① IO用来处理设备之间的数据传输
② Java对数据操作是通过流的方式
③ Java用来操作流的对象都在IO包中
④ 流按操作数据分为:字符流和字节流
⑤ 流按流向操作分为:输入流和输出流

二、IO流的分类

1.根据处理的数据单位分为字节流和字符流

● 字节流:操作的数据单元是8位的字节。以InputStream、OutputStream作为抽象基类。
● 字符流:操作的数据单元是字符,以Reader、Writer作为抽象基类。

字节流可以处理所有数据文件,若处理的是纯文本数据,建议使用字符流。

2.根据流的作用可以分为节点流和处理流

● 节点流:程序直接与数据源连接,和实际的输入/输出节点连接;
● 处理流:对节点流进行包装,扩展原来的功能,由处理流执行IO操作。

处理流的作用可分类:处理流可以隐藏底层设备上节点流的差异,无需关心数据的来源,程序只需要通过处理流执行IO操作。处理流以节点流作为构造参数。通常情况下,推线使用处理流来完成IO操作。

1.缓冲流:提供一个缓冲区,能够提高输入/输出的执行效率,减少同节点的频繁操作。例如:BufferedInputStream/BuffferedOutputStream
2.转换流:将字节流转成字符流。字节流使用范围广泛,但字符流更方便。例如一个字节流的数据源是纯文本,转成字符流来处理会更好。InputStreamReader/OutputStreamWriter
3.打印输出流:打印输出指定内容,根据构造参数中的节点流来决定输出到何处。PringStream:打印输出字节数据 / PrintWriter:打印输出文本数据

三、字符流和字节流

1、字符流

字符流的由来:字节流+编码表 - 其实是字节流读取文字字节数据后,不直接操作而是先查指定的编码表。获取对应的文字。

字符流操作的数据单元是字符。以Writer、Reader作为抽象基类。
技术图片
|- Reader:字符读取流
  |- BufferedReader:字符读取缓冲区     |- LIneNumberReader:增加行号设置与获取   |- CharArrayReader:字符数组输出流   |- StringReader:其源为一个字符串的字符流   |- InputStreamReader:字节转换字符的桥梁,解码     |- FileReader:文本文件读取流(文件阅读器) |- Wirter:字节写入流
  |- BufferedWriter:字符写入缓冲区   |- CharArrayWriter:字符数组写入流   |- StringWriter:一个字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。   |- PrintWriter:字符打印流,操作文件的字节流+本机默认的码表。   |- OutputStreamWriter:字符转换字节的桥梁,编码     |- FileWriter:文本文件写入流(文件输出流)

2、字节

● 将外设中的数据读取到内存中:输入
● 将内存中的数据写入到外设中:输出
字节流操作的数据单元是8位的字节。InputStream、OutputStream作为抽象基类。技术图片
|- InputStream(输入流):抽象类,输入流顶层基类
  |- BufferedInputStream(字节输入缓冲区):字节缓冲输入流,提高了读取效率。
  |- FileInputStream(文件输入流):字节文件输入流,从文件系统中的某个文件中获得输入字节,用于读取诸如图像数据之类的原始字节流。
  |- ObjectInputStream(对象输入流):封装了对其它类型数据的读取操作,构造函数传递需要InputStream子类的对象
|- OutputStream(输出流):抽象类,输出流顶层基类|- BufferedOutputStream(字节输出缓冲区):字节缓冲输出流,提高了写出效率。
  |- FileOutputStream(文件输出流):字节文件输出流是用于将数据写入到File,从程序中写入到其他位置。输出的目的地文件不存在,则会自动创建,不指定盘符的话,默认创建在项目目录下
  |- ObjectOutputStream(对象输出流):封装了对其它类型数据的写入操作,构造函数传递需要OutputStream子类的对象

3、字节流和字符流的区别:

● 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
● 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
● 字节流:一次读入或读出是8位二进制。
● 字符流:一次读入或读出是16位二进制。

设备上的数据无论是图片或者视频,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。

结论只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

四、节点流和处理流

1.节点流

节点流:直接与数据源相连,读入或读出。

直接使用节点流,读写不方便,为了更快的读写文件,才有了处理流。

技术图片

常用的节点流:

● 父 类 :InputStream 、OutputStream、 Reader、 Writer
● 文 件 :FileInputStream 、 FileOutputStrean 、FileReader 、FileWriter 文件进行处理的节点流
● 数 组 :ByteArrayInputStream、 ByteArrayOutputStream、 CharArrayReader 、CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
● 字符串 :StringReader、 StringWriter 对字符串进行处理的节点流
● 管 道 :PipedInputStream、PipedOutputStream 、PipedReader 、PipedWriter 对管道进行处理的节点流

2.处理流

处理流和节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

技术图片

常用的处理流

● 缓冲流:BufferedInputStrean 、BufferedOutputStream、 BufferedReader、 BufferedWriter 增加缓冲功能,避免频繁读写硬盘。
● 转换流:InputStreamReader 、OutputStreamReader 实现字节流和字符流之间的转换。
● 数据流: DataInputStream 、DataOutputStream 等,提供将基础数据类型写入到文件中,或者读取出来。
缓冲流 - 字符流缓冲区 - 高效缓冲区

缓冲机制用于应用程序和物理数据时降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。

比如:快递寄送点,并不是每收一个寄件就发送出去,而是收集到一定数量或一定时间后再整体发送。

BufferedWriter:
 - newLine():写入一个行分隔符
 - flush():刷新该流中的缓冲
BufferedReader:
 - readLine():读取一行文本数据

五、IO流的操作规律

流的操作规律:想要知道开发时用到哪些对象。只要通过四个明确即可。

1,明确源和目的(汇)
  源:InputStream Reader
  目的:OutputStream Writer
2,明确数据是否纯文本
  源:是纯文本:Reader
    不是纯文本:InputStream
  目的:是纯文本:Writer
    不是纯文本:OutputStream
3,明确具体的设备
  源:硬盘:File
    控制台:System.in
    内存:数组
    网络:Socket流
  目的:硬盘:File
    控制台:System.out
    内存:数组
    网络:Scoket流
4,是否需要其他额外功能
  #1,是否需要高效(缓冲区)
    是就加上Buffer。
  #2,转换。
    InputStreamReader
    OutputStreamWriter
- 什么时候使用转换流呢?
  1,源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁。 提高对文本操作的便捷。 
  2,一旦操作文本涉及到具体的指定编码表时,必须使用转换流 。

六、装饰设计模式

装饰模式(Decorator)动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活。

装饰模式的应用:

- 何时使用:
  在不想增加很多子类的情况下进行扩展。
- 方法:
  将具体功能职责划分,同时继承装饰者模式。
- 优点:
  装饰类和被装饰类可以独立发展,而不会相互耦合。它有效地把类的核心职责和装饰功能分开了
  装饰模式是继承关系的一个替代方案
  装饰模式可以动态地扩展一个实现类的功能
- 缺点:
  多层装饰比较复杂。一旦出现了问题需要一层一层检查,工作量巨大
- 使用场景:
  扩展一个类的功能时
  需要动态地给一个对象增加功能,并可以动态的撤销时
  需要为一批兄弟类进行改装或者加装功能时
- 应用实例:
  旧机包装成新机,手机/电脑内部配置不变,只是换了个外壳
  换衣小游戏,人还是那个人,不断给他换衣服,还可以一层套一层
  孙悟空72变,变成什么后就有了它的功能,但本质还是一只猴子

继承与装饰模式的区别

Writer加入缓冲技术

TextWriter:用于操作文本
MediaWriter:用于操作媒体

● 使用继承进行功能扩展

|- Writer:继承模式提高效率的体系
  |- TextWriter:用于操作文本
    |- BufferedTextWriter:加入了缓冲技术的操作文本的对象
  |- MediaWriter:用于操作媒体
    |- BufferedMediaWriter:

使用继承进行功能扩展,这个体系又多了流对象。如果流要提高效率,这个流也要产生子类。只是为提高功能效率,进行的继承。

导致继承体系越来越臃肿。这样不够灵活

● 使用设计装饰模式进行功能扩展在原有功能的基础上,新增功能,降低继承所带来的耦合性

|- Writer:使用装饰模式提高效率的体系
  |- TextWriter:用于操作文本
  |- MediaWriter:用于操作媒体
  |- BufferWriter:用于提高效率的

继承是让缓冲和具体的对象相结合。

将缓冲进行单独的封装,那个对象需要缓冲就将那个对象和缓冲相关联。

class Buffer{
    Buffer(TextWriter t){
    }
    Buffer(MediaWriter m){
    }
}
class BufferWriter extends Writer{
    BufferWriter(Writer w){
    }
}

装饰比继承灵活

  特点装饰类和被装饰类都必须所属同一个接口或者父类。

装饰和继承都能实现一样的特点进行功能的扩展增强。

以上是关于Java - IO(Input Output)流的主要内容,如果未能解决你的问题,请参考以下文章

Java Input/Output

io流(input output)

廖雪峰Java6 IO编程-2input和output-4Filter模式

廖雪峰Java6 IO编程-2input和output-7序列化

IO(Input&Output)流の介绍

Java学习之IO流一