黑马程序员-IO流(概念、体系)

来源:互联网 发布:ubuntu x screen分辨率 编辑:程序博客网 时间:2024/05/21 10:00

-----------android培训java培训、java学习型技术博客、期待与您交流! ------------



一、IO技术

 

1、IO技术是什么?


简单来说,IO技术就是应用程序对存储设备内数据的操作,该操作分为读取和写入。

比如说,打开一个txt文件,这就是个IO技术,应用程序读取硬盘中的数据。

 

2、为什么需要IO技术?


在我们日常使用的几乎所有的程序在完成特定的任务都需要与数据存储设备进行数据交换,最常见的数据存储设备主要有磁盘和网络,IO技术就是指应用程序对这些数据存储设备的数据输入和输出。

 

3、IO技术好处是什么?


IO技术的存在,实现了应用程序和存储设备之间数据的交换 ,也可以理解为应用程序可以根据人为发出的指令动态的处理数据存储设备中的数据,实现人机信息的交换。

4、IO技术操作存储设备内的数据是通过什么来实现的呢?


IO技术操作存储设备内的数据是通过来实现的。

 

二、流

 

1、定义


流是一个抽象的概念,代表一串数据的集合,可以理解为数据的流动,就是一个数据流。当java程序需要从数据源读取数据时, 就需要开启一个到数据源的流;同样,当程序需要输出数据到目的的时,也需要开启一个流,流的创建是为了更方便的处理数据的输入和输出。


2、怎么样理解流?


可以把数据流比喻成现实生活中的水流,每户人家都需要自来水,就需要在家喝自来水厂之间建一根水管,这样水厂的水才能通过水管流到家中。

自来水厂就是数据源(数据存数设备),家就是应用程序,水管就是读取方法,水流就是流,数据就是水。

应用程序要读取数据源中的数据,存储设备中的数据通过水流沿着水管就流到了应用程序中了。如下图:

3、流的分类:


(1)输入流(读)和输出流(写)。

(2)处理数据的不同,分为字节流和字符流。

 

           1)字节流:处理字节数据的流对象。

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

在java1.0中,类库的设计者首先限定与输入有关的所有类都应该从InputStream继承,而与输出有关的所有类都应该从OutputStream继承。

 

            2)字符流:处理字符数据的流对象。

java1.1对基本的IO流类库进行了重大修改。加入了字符流Reader和Writer,处理字符数据。

为什么要有字符流呢?

因为每个国家的字符不一样,所以涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,所以需要获取中文字节数据的同时+指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。它只能操作字符数据。操作字符优先考虑字符流体系。

 

4、核心IO流的体系


流的体系功能不同,但是有共性内容,不断抽取,形成继承体系。该体系一共有四个基类,而且都是抽象类。


                                                            字节流                 字符流
 
                                     输入流      InputStream           Reader
 
                                     输出流      OutputStream        Writer
 


(1)InputStream:此抽象类是表示字节输入流的所有类的超类。是用来表示那些从不同数据源(字节数组、文件、管道、合并流)产生的输入的类。每一种数据源都有相应的InputStream子类。

|--- ByteArrayInputStream:创建一个新的 byte 数组输入流。在创建它的实例时,从外部传入一个byte型数组当做其内存缓冲区,实例从缓冲区中读出byte型数据转化为InputStream。
|--- FileInputStream:从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。
|--- PipedInputStream:管道流,线程间通信,与PipedOutputStream配合使用
|--- FilterInputStream:抽象类,作为“装饰器”的接口。该“装饰器”把属性或有用的接口与其他的InputStream类组合在一起。
|--- SequenceInputStream:合并流,将多个输入流逻辑串联。

(2)OutputStream:此抽象类是表示字节输出流的所有类的超类。该类型的类决定了输出所要去往的目标(字节数组、文件、管道)。
|--- ByteArrayOutputStream:创建一个新的 byte 数组输出流。在创建它的实例时,程序内部创建一个byte型数组的缓冲区,实例向缓冲区中写入byte型数据,作为OutputStream,然后将缓冲区中的数据写入程序外部的内存字节数组中。
|--- FileOutputStream:文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。
|--- PipedOutputStream:管道流,线程间通信,与配合使用
|--- FilterOutputStream:抽象类,此类是装饰输出流的所有类的超类,作为“装饰器”的接口。该“装饰器”为其他的OutputStream类提供有用功能组合。

 

(3)Reader:用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。
|---CharArrayReader:
|---FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。

|---StringReader:
|---PipedReader:
|---Filter
Reader:


(4)Writer:写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。
|---CharArrayWriter:
|---FileWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。
|---StringWriter:
|---PipedWriter:
|---Filter
Writer:



5、装饰器类


(1)FilterInputStream、FilterOutputStream

是用来提供装饰器类接口以控制特定输入流和输出流的两个类,它们的名字起的并不好,因为其作用不是过滤而是装饰。

它们从InputStream和OutputStream派生而来,因为它们必须为被修饰的对象提供通用接口。

1)FilterInputStream:
        |--- DataInputStream:
        |--- BufferedInputStream:该类实现缓冲的输入流。

2)FilterOutputStream:
        |--- DataOutputStream:
        |--- BufferedOutputStream:该类实现缓冲的输出流。
        |--- PrintStream:


(2)FilterReader、FilterWriter、BufferedReader、bufferedWriter、PrintWriter

这五个类是相互独立的,没有子父类关系

1)FilterReader:

2)FilterWriter:

3)BufferedReader:

4)bufferedWriter:

5)PrintWriter:


6、缓冲区:


(1)缓冲区的作用:

缓冲区的出现是为了提高流的操作效率而出现的,所以在创建缓冲区之前,必须要先有流对象。

 

(2)缓冲区的分类:


                                   字节流                          字符流
 
      输入流   BufferedInputStream       BufferedReader
 
      输出流   BufferedOutputStream    BufferedWriter
 


(3)readLine()方法

BufferedReader中特有的一次读一行的读取方法:readLine()方法,返回null时,表示读到文件末尾。

注:readLine()方法返回的时候只返回回车符之前的数据内容,并不能返回回车符,通俗来说,readLine()方法读取不了回车符,读取文件内容时换不了行

解决readLine()读取文件换不了行方法: newLine()  换行,在每次读一行后调用换行方法,继续读这样就按照原文本格式把文件中数据读出来了。

7、转换流:

读取转换流:      InputStreamReader    字节流通向字符流的桥梁
写入转换流:      outputStreamWriter    字符流通向字节流的桥梁
 

8、打印流:

字节打印流:        printStream
字符打印流:        printWriter


9、合并流:SequenceInputStream类

合并流又称序列流,合并流思想:有很多的源和同一个目的相连,比如说源1,源2,源3,同时和目的1相连,合并流将源1,源2,源3作为对象分装到集合中,将集合放入SequenceInputStream(List)中,将SequenceInputStream类对象,作为源4,和目的1相连,这样就不用创建4个流和目的1相连,只需源4和目的间创立一个流相连即可,提高了效率。



10、对象流:

对象输入流   ObjectprintStream
对象输出流   ObjectprintWriter

 

11、管道流:

管道输入流   PipedInputStream
管道输出流   PipedOutputStream
 

三、(重点)流操作的规律:


1、流操作的难点:

流对象很多,不知道具体用哪个


2、思考步骤:


(1)第一步:先明确源和目的


数据源:就是需要读取,可以使用两个体系:
文本:用Reader(字符输出流,读取流)
字节:用InputStream(字节输入流,读取流)


数据汇:就是需要写入,可以使用两个体系:
文本:用Writer(字符输入流,写入流)
字节:用OutputStream(字节输出流,写入流)


(2)第二步:明确是不是纯文本


是:用字符流;

数据源:Reader
数据汇:Writer 

不是:用字节流

数据源:InputStream
数据汇:OutputStream


(3)第三步:明确流体系后,通过设备来明确具体使用哪个流对象


数据源对应的设备:
键盘:System.in
硬盘:文件流File
内存:数组流ArrayStream


数据汇对应的设备:
控制台:System.out
硬盘:文件流File
内存:数组流ArrayStream


(4)第四步:需要在基本操作上附加其他功能吗?比如缓冲。


如果需要就进行装饰。

1)是否需要高效?缓冲区Buffered 四个。

2)是否需要转换?转换流 InputStreamReader OutputStreamWriter

3)是否操作基本数据类型? DataInputStream  DataOutputStream

4)是否操作对象(对象序列化)? ObjectInputStream ObjectOutputStream

5)需要对多个源合并吗? SequenceInputStream

6)需要保证数据的表现形式到目的地吗? PrintWriter

原创粉丝点击