第六课 java的流IO

1 IO的定义

Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。IO又分为流IO(java.io)和块IO(java.nio),Java.io是大多数面向数据流的输入/输出类的主要软件包。此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO。
流IO的好处是简单易用,缺点是效率较低。块IO效率很高,但编程比较复杂。

2 流的定义

在电脑上的数据有三种存储方式,一种是外存,一种是内存,一种是缓存。比如电脑上的硬盘,磁盘,U盘等都是外存,在电脑上有内存条,缓存是在CPU里面的。外存的存储量最大,其次是内存,最后是缓存,但是外存的数据的读取最慢,其次是内存,缓存最快。这里总结从外存读取数据到内存以及将数据从内存写到外存中。对于内存和外存的理解,我们可以简单的理解为容器,即外存是一个容器,内存又是另外一个容器。
在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流等等,java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。将数据从外存中读取到内存中的称为输入流,将数据从内存写入外存中的称为输出流

3 IO流的分类

(1)根据流向
1)输出流:把程序(内存)中的内容输出到磁盘、光盘等存储设备中
2)输入流:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中

(2)根据传输数据单位
1)字节流:数据流中最小的数据单元是字节
2)字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节(无论中文还是英文都是两个字节)。

(3)根据功能
1)节点流:可以从或向一个特定的地方(节点)读写数据,直接连接数据源。如最常见的是文件的FileReader,还可以是数组、管道、字符串,关键字分别为ByteArray/CharArray,Piped,String.
2)处理流(包装流):并不直接连接数据源,是对一个已存在的流的连接和封装,是一种典型的装饰器设计模式,使用处理流主要是为了更方便的执行输入输出工作,如PrintStream,输出功能很强大,又如BufferedReader提供缓存机制,推荐输出时都使用处理流包装。

4 IO流特性

(1)先进先出,最先写入输出流的数据最先被输入流读取到。

(2)顺序存取,可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile可以从文件的任意位置进行存取(输入输出)操作)

(3)只读或只写,每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。

(4)IO操作的模板
操作 IO 流的模板:

①、创建源或目标对象

输入:把文件中的数据流向到程序中,此时文件是 源,程序是目标

输出:把程序中的数据流向到文件中,此时文件是目标,程序是源

②、创建 IO 流对象

输入:创建输入流对象

输出:创建输出流对象

③、具体的 IO 操作

④、关闭资源

输入:输入流的 close() 方法

输出:输出流的 close() 方法

5 java.io包的整体架构

在整个Java.io包中最重要的就是5个类和一个接口。5个类指的是File、OutputStream、InputStream、Writer、Reader;一个接口指的是Serializable

5.1 字节流

5.1.1 InputStream

InputStream这个抽象类是所有基于字节的输入流的超类,抽象了Java的字节输入模型。

5.1.1.1 ByteArrayInputStream

(1)作用
主要是用来读取字节数组
(2)特点
【1】输入流
【2】字节流
【3】节点流,数据源一般是字节数组
【4】操作字节数组
【5】包含缓冲区

(3)常用方法
底层用来一个字节数组来保存数据,也就是内部缓冲区,方法用synchronize加锁
核心方法,Override(重写)了抽象类InputStream的read方法:
【1】read()的作用是从字节流中“读取下一个字节”。
【2】read(byte b[], int off, int len)的作用是从字节流(缓冲区)读取字节数据,并写入到字节数组b中。off是将字节写入到b的起始位置,length是写入的字节的长度

5.1.1.2 FileInputStream

(1)作用
主要是用来读取文件
(2)特点
【1】输入流
【2】字节流
【3】节点流,数据源一般是文件
【4】操作文件

(3)常用方法
底层实现基本都是调用native方法。三个核心方法,也就是Override(重写)了抽象类InputStream的read方法;
【1】read():直接从文件输入流中读取一个字节
【2】read(byte b[]):从文件输入流中读取,从0句柄开始的b.length个字节,并存储至b字节数组内
【3】read(byte b[], int off, int len):从文件输入流中读取,从off句柄开始的len个字节,并存储至b字节数组内

5.1.1.3 ObjectInputStream

(1)作用
反序列化
(2)特点
【1】输入流
底层:ObjectInputStream=》BlockDataInputStream=》PeekInputStream=》被包装的流,通常是FileInputStream
【2】字节流
【3】处理流
【4】操作对象
【5】包含缓冲区

(3)常用方法
【1】readObject()
Final方法,子类重写只能通过readObjectOverride

5.1.1.4 PipedInputStream

(1)作用
内部使用字节数组,也就是缓冲区,也就是管道大小,它们的作用是让多线程可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedOutputStream和PipedInputStream配套使用。使用管道通信时,大致的流程是:我们在线程A中向PipedOutputStream中写入数据,这些数据会自动的发送到与PipedOutputStream对应的PipedInputStream中,进而存储在PipedInputStream的缓冲中;此时,线程B通过读取PipedInputStream中的数据。就可以实现,线程A和线程B的通信。

(2)特点
【1】输入流
【2】字节流
【3】节点流,数据源一般是管道,管道本质是一个字节数组
【4】操作管道
【5】包含缓冲区

(3)常用方法
【1】read()
管道(的缓冲)中读取一个字节,并将其转换成int类型
【2】read(byte b[], int off, int len)
从管道(的缓冲)中读取数据,并将其存入到数组b中
【3】receive
接收int类型的数据b,写入缓冲区
【4】receive(byte b[], int off, int len)
接收字节数组b,写入缓冲区
【5】connect
管道连接,将“管道输入流”和“管道输出流”关联起来

5.1.1.5 SequenceInputStream

(1)作用
有些情况下,当我们需要从多个输入流中向程序读入数据,序列流主要用来合并多个流,然后顺序读取每个流,比如将多个文件合并成一个文件
(2)特点
【1】输入流
【2】字节流
【3】处理流,没数据源,包装其他流,从其他流读取
【4】操作其他节点输入流

(3)常用的方法
【1】read()
方法读取当前输入流中数据的下一个字节
【2】read(byte[] b, int off, int len)
将最多 len 个数据字节从此输入流读入 byte 数组。

5.1.1.6 StringBufferInputStream

(1)作用
读取字符串的内容
(2)特点
【1】输入流
【2】字节流
【3】节点流,数据源就是字符串
【4】操作字符串
【5】包含缓冲区

(3)常用方法
【1】read()
方法读取当前输入流中数据的下一个字节
【2】read(byte[] b, int off, int len)
将最多 len 个数据字节从此输入流读入 byte 数组。

5.1.1.7 FilterInputStream

过滤器字节输入流,这里用到了装饰器模式,它的主要用途在于给一个对象动态的添加功能。FilterInputStream仅仅是对InputStream中所有方法进行了重写,并且只是调用传入的InputStream子类的方法,话句话说就是没有对传入的低级字节输入流进行任何的装饰,它们的作用是为所有字节输入流的装饰类提供一个标准、一个类似于接口的作用,具体的装饰功能由FilterInputStream的子类来完成

5.1.1.7.1 BufferedInputStream

(1)作用
提供了经过测试的缓冲数组,默认8k,减少对磁盘的访问来提高读取速度,当然底层也是用了节点流的read(byte[] b, int off, int len),只是它帮我们写好了并且提供了很多其他的操作
(2)特点
【1】输入流
【2】字节流
【3】处理流,数据源其他节点流
【4】操作其他节点流
【5】包含缓冲区

(3)常用方法
用到了synchronized同步锁机制和cas乐观锁机制
【1】read()
从缓冲区读取一个字节
【2】read(byte[] b, int off, int len)
将最多len 个数据字节从缓冲区off位置开始读入 byte 数组。

5.1.1.7.2 DataInputStream

(1)作用
是用来装饰其它输入流,它“允许应用程序以与机器无关方式(不用去关注编码格式)从底层输入流中读取基本 Java 数据类型”。

(2)特点
【1】输入流
【2】字节流
【3】处理流,数据源其他节点流
【4】操作其他节点流
【5】包含缓冲区

(3)常用的方法
都是final,不可以被重写
【1】read(byte b[])
从底层数据流中读取一个字节到到字节数组中
【2】read(byte b[], int off, int len)
从“数据输入流”中读取数据并存储到字节数组b中。off是字节数组b中开始存储元素的起始位置。len是读取字节的个数。
【3】readFully(byte b[])
从“数据输入流”中读取数据并填满字节数组b中;没有填满数组b则一直读取,直到填满,字节数组b中开始存储元素的起始位置是0。读取字节的个数数组长度。
【4】readFully(byte b[], int off, int len)
从“数据输入流”中读取数据并存储到字节数组b中;若没读取len个字节,直到一直读取直到读取完len个字节为止。
【5】readBoolean()
从“数据输入流”中读取boolean类型的值
【6】byte readByte()
从“数据输入流”中读取Byte类型的值
【7】int readUnsignedByte()
从“数据输入流”中读取“无符号的Byte类型”的值,即读取值为正数的byte值
【8】readShort()
从“数据输入流”中读取“short类型”的值
【9】readUnsignedShort()
从“数据输入流”中读取“无符号的short类型”的值
【10】readChar()
从“数据输入流”中读取“char类型”的值
【11】readInt()
从“数据输入流”中读取“int类型”的值
【12】readLong()
从“数据输入流”中读取“long类型”的值
【13】readFloat()
从“数据输入流”中读取“float类型”的值
【14】readDouble()
从“数据输入流”中读取“double类型”的值
【15】readLine()
从“数据输入流”中读取一行字符串
【16】readUTF()
从输入流中读取UTF-8编码的数据,并以String字符串的形式返回。

5.1.1.7.3 PushBackInputStream

(1)主要作用
常情况下我们从流中读取数据时都是顺序操作的,也许流中的数据并不都是我们需要的,按照平常的流,我们要做的是就是将流中的数据依读取取出,并对取出的数据进行筛选,不符合条件的数据就丢弃。PushbackInputStream流则稍有不同,它通过内部的一个缓存从而支持了数据的回推,在上述场景下,当遇到不需要的数据时,PushbackInputStream还可以将数据重新推回到流中,其实只是保存在缓冲区,下次读取的时候优先读取
(2)特点
【1】输入流
【2】字节流
【3】处理流,数据源其他节点流
【4】操作其他节点流
【5】包含缓冲区
仅仅保存pushBack的字节,并且这个字节数组是从后往前写入的,先写下标大的

(3)常用方法
【1】read()
每次读取一个字节的数据。从方法中可以看出,优先读取回推缓存中的数据,如果回推缓存中没有数据,那么就正常调用底层InputStream对应的read方法
【2】read(byte[] b, int off, int len)
一次读取多个字节的read方法,其包含三个参数,第一个为承载读取的数据的字节数组,第二个参数为从数组的哪个位置开始存储数据,第三个参数则是要进行存储的数据长度。
【3】unread(int b)
一次回推一个字节数据到缓冲区
【4】unread(byte[] b, int off, int len)
一次可以回推多个字节数据,第一个参数为一个byte型数组,用于存放所要进行回推操作的数据,第二和第三个参数都是一个int型数值,分别代表从传入的数组中取出数据的起点,以及其需要回推的数据长度。
【5】unread(byte[] b)
一次可以回推多个字节数据的unread方法,将传入的数组的所有数据都回推到内置缓存中去

5.1.2 OutputStream

OutputStream这个抽象类是所有基于字节的输出流的超类,抽象了Java的字节输出模型。

5.1.2.1 ByteArrayOutputStream

(1)作用
主要是用来写入字节数组
(2)特点
【1】输出流
【2】字节流
【3】节点流,数据源一般是字节数组
【4】操作字节数组
【5】包含缓冲区

(3)常用方法
底层用来一个字节数组来保存数据,也就是内部缓冲区,方法用synchronize加锁
核心方法,Override(重写)了抽象类InputStream的write方法:
【1】write(int a)
作用是写入1个字节数据到字节流(缓冲区)
【2】write(byte b[], int off, int len)
作用是将字节数组b的字节数据写入到字节流(缓冲区)。off是将字节数组b的起始位置,length是写入的字节的长度

5.1.2.2 FileOutputStream

(1)作用
主要是用来写文件
(2)特点
【1】输出流
【2】字节流
【3】节点流,数据源一般是文件
【4】操作文件

(3)常用方法
底层实现基本都是调用native方法。三个核心方法,也就是Override(重写)了抽象类InputStream的write方法;
【1】write(int b)
直接将指定的字节b写入文件输出流
【2】write(byte b[])
将整个字节数组写入文件输出流
【3】write(byte b[], int off, int len)
从字节数组b的off句柄开始的len个字节,写入文件输出流

5.1.2.3 ObjectOutputStream

(1)作用
序列化
(2)特点
【1】输出流
底层:ObjectOutputStream=》BlockDataOutputStream=》PeekOutputStream=》被包装的流,通常是FileOutputStream
【2】字节流
【3】处理流
【4】操作对象
【5】包含缓冲区

(3)常用方法
【1】writeObject()
Final方法,子类重写只能通过writeObjectOverride

5.1.2.4 PipedOutputStream

(1)作用
内部使用字节数组,也就是缓冲区,也就是管道大小,它们的作用是让多线程可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedOutputStream和PipedInputStream配套使用。使用管道通信时,大致的流程是:我们在线程A中向PipedOutputStream中写入数据,这些数据会自动的发送到与PipedOutputStream对应的PipedInputStream中,进而存储在PipedInputStream的缓冲中;此时,线程B通过读取PipedInputStream中的数据。就可以实现,线程A和线程B的通信。

(2)特点
【1】输出流
【2】字节流
【3】节点流,数据源一般是管道,管道本质是一个字节数组
【4】操作管道
【5】包含缓冲区

(3)常用方法
【1】write(int b)
底层调用输入流的receive方法,往管道(的缓冲)中写入一个字节
【2】write(byte b[], int off, int len)
底层调用输入流的receive方法,往管道(的缓冲)中写入字节数组b从off位置开始len长的字节数据
【3】connect
连接输入流

5.1.2.5 FilterOutputStream

过滤器字节输出流,这里用到了装饰器模式,它的主要用途在于给一个对象动态的添加功能。FilterOutputStream仅仅是对OutputStream中所有方法进行了重写,并且只是调用传入的OutputStream子类的方法,话句话说就是没有对传入的低级字节输入流进行任何的装饰,它们的作用是为所有字节输出流的装饰类提供一个标准、一个类似于接口的作用,具体的装饰功能由FilterOutputStream的子类来完成

5.1.2.5.1 BufferedOutputStream

(1)作用
提供了经过测试的缓冲数组,默认8k,减少对磁盘的访问来提高写入速度,当然底层也是用了节点流的write(byte[] b, int off, int len),只是它帮我们写好了并且提供了很多其他的操作
(2)特点
【1】输出流
【2】字节流
【3】处理流,数据源其他节点流
【4】操作其他节点流
【5】包含缓冲区

(3)常用方法
用到了synchronized同步锁机制和cas乐观锁机制
【1】write()
写入一个字节到缓冲区
【2】write(byte[] b, int off, int len)
将字节数组b从off位置开始的最多len 个数据字节写入缓冲区

5.1.2.5.2 DataOutputStream

(1)作用
是用来装饰其它输出流,它“允许应用程序以与机器无关方式(不用去关注编码格式)从底层输出流中写入基本 Java 数据类型”。

(2)特点
【1】输出流
【2】字节流
【3】处理流,数据源其他节点流
【4】操作其他节点流
【5】包含缓冲区

(3)常用的方法
都是final,不可以被重写
【1】write(int b)
将int类型的值写入到“数据输出流”中,实际只写入一个字节
【2】write(byte b[], int off, int len)
将字节数组b从off开始的len个字节,都写入到“数据输出流”中
【3】readFully(byte b[])
从“数据输入流”中读取数据并填满字节数组b中;没有填满数组b则一直读取,直到填满,字节数组b中开始存储元素的起始位置是0。读取字节的个数数组长度。
【4】writeBoolean()
写入boolean类型的值到“数据输出流”中
【5】writeByte(int v)
写入Byte类型的值到“数据输出流”中
【6】writeBytes(String s)
写入字符串(多个字节)到“数据输出流”中
【7】writeChar(int v)
写一个字符(2个字节)到“数据输出流”中
【8】writeChars(String s)
写多个字符(多个字节)到“数据输出流”中
【9】writeShort(int v)
写入Short类型的值到“数据输出流”中
【10】writeInt(int v)
写入int类型的值到“数据输出流”中
【11】writeLong(long v)
写入long类型的值到“数据输出流”中
【12】writeFloat(float v)
写入float类型的值到“数据输出流”中
【13】writeDouble(double v)
写入double类型的值到“数据输出流”中
【14】writeUTF(String str)
写入String类型的值到“数据输出流”中,使用UTF8编码

5.1.2.5.3 PrintStream

(1)作用
是用来装饰其它输出流,方便地打印各种数据值表示形式

(2)特点
【1】输出流
【2】字节流
【3】处理流,数据源其他节点流
【4】操作其他节点流

(3)常用方法
【1】append(char c)
将“字符c”追加到“PrintStream输出流中”
【2】append(CharSequence charSequence, int start, int end)
将“字符序列从start(包括)到end(不包括)的全部字符”追加到“PrintStream输出流中”
【3】append(CharSequence charSequence)
将“字符序列的全部字符”追加到“PrintStream输出流中”
【4】format(Locale l, String format, Object… args)
根据“Locale值(区域属性)”来格式化数据
【5】format(String format, Object… args)
根据“默认的Locale值(区域属性)”来格式化数据
【6】print(float f)
将“float数据f对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
【7】print(double d)
将“double数据d对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
【8】print(String str)
将“字符串数据str”写入到“PrintStream输出流”中,print实际调用的是write函数
【9】print(Object o)
将“对象o对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
【10】print(char c)
将“字符c对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
【11】print(char[] chars)
将“字符数组chars对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
【12】print(long l)
将“long型数据l对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
【13】print(int i)
将“int数据i对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
【14】print(boolean b)
将“boolean数据b对应的字符串”写入到“PrintStream输出流”中,print实际调用的是write函数
【15】printf(Locale l, String format, Object… args)
将“数据args”根据“Locale值(区域属性)”按照format格式化,并写入到“PrintStream输出流”中
【16】printf(String format, Object… args)
将“数据args”根据“默认Locale值(区域属性)”按照format格式化,并写入到“PrintStream输出流”中
【17】println()
将“换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
【18】println(float f)
将“float数据对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
【19】println(int i)
将“int数据对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
【20】println(long l)
将“long数据对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
【21】println(Object o)
将“对象o对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
【22】println(char[] chars)
将“字符数组chars对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
【23】println(String str)
将“字符串str+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
【24】println(char c)
将“字符c对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
【25】println(double d)
将“double数据对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
【26】println(boolean b)
将“boolean数据对应的字符串+换行符”写入到“PrintStream输出流”中,println实际调用的是write函数
【27】write(int oneByte)
将数据oneByte写入到“PrintStream输出流”中。oneByte虽然是int类型,但实际只会写入一个字节
【28】write(byte[] buffer, int offset, int length)
将“buffer中从offset开始的length个字节”写入到“PrintStream输出流”中。

5.2 字符流

扩展:有空可以研究下java的编码解码

5.2.1 Reader

字符输入流的抽象父类,读取的最小单位是字符

5.2.1.1 CharArrayReader

(1)作用
主要是用来读取字符数组
(2)特点
【1】输入流
【2】字符流
【3】节点流,数据源一般是字符数组
【4】操作字符数组
【5】包含缓冲区

(3)常用方法
底层用来一个字符数组来保存数据,也就是内部缓冲区,方法用synchronize加锁
核心方法,Override(重写)了抽象类Reader的read方法:
【1】read()
读取下一个字符。即返回字符缓冲区中下一位置的值
【2】read(char b[], int off, int len)
读取数据,并保存到字符数组b中从off开始的位置中,len是读取长度。

5.2.1.2 InputStreamReader

(1)作用
字节流通向字符流的桥梁。底层使用StreamDecoder对输入字节流进行包装,从输入流读取到字节数组,然后利用CharSetDecoder进行解码
(2)特点
【1】输入流
【2】字符流
【3】处理流,数据源一般是字节流
【4】操作字节流

(3)常用方法
【1】read()
从输入流中读取一个字符

【2】read(char cbuf[], int offset, int length)
从输入流读取多个字符,并保存到字符数组b中从off开始的位置中,len是读取长度

5.2.1.2.1 FileReader

(1)作用
包装FileInputStream,然后基本都是集成了父类InputStreamReader的方法,
特点和常用方法也和InputStreamReader一样

5.2.1.3 StringReader

(1)作用
读取字符串的内容
(2)特点
【1】输入流
【2】字符流
【3】节点流,数据源就是字符串
【4】操作字符串
【5】包含String类型的变量,存放要读取的内容
(3)常用方法
【1】read()
方法读取当前输入流中数据的下一个字符
【2】read(char[] b, int off, int len)
将最多 len 个数据字节从此输入流读入 char 数组。

5.2.1.4 PipedReader

(1)作用
内部使用字符数组,也就是缓冲区,也就是管道大小,它们的作用是让多线程可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedWriter和PipedReader配套使用。使用管道通信时,大致的流程是:我们在线程A中向PipedWriter中写入数据,这些数据会自动的发送到与PipedWriter对应的PipedReader中,进而存储在PipedReader的缓冲中;此时,线程B通过读取PipedReader中的数据。就可以实现,线程A和线程B的通信。

(2)特点
【1】输入流
【2】字符流
【3】节点流,数据源一般是管道,管道本质是一个字符数组
【4】操作管道
【5】包含缓冲区

(3)常用方法
【1】read()
管道(的缓冲)中读取一个字符,并将其转换成int类型
【2】read(char b[], int off, int len)
从管道(的缓冲)中读取数据,并将其存入到数组b中
【3】receive
接收int类型的数据b,写入缓冲区
【4】receive(char b[], int off, int len)
接收字符数组b,写入缓冲区
【5】connect
管道连接,将“管道字符输入流”和“管道字符输出流”关联起来

5.2.1.5 BufferedReader

(1)作用
提供了经过测试的缓冲数组,默认8k,减少对磁盘的访问来提高读取速度,当然底层也是用了节点流的read(char[] b, int off, int len),只是它帮我们写好了并且提供了很多其他的操作,不然我们用底层的节点流方法也是可以的
(2)特点
【1】输入流
【2】字符流
【3】处理流,数据源其他节点流
【4】操作其他节点流
【5】包含缓冲区

(3)常用方法
用到了synchronized同步锁机制和cas乐观锁机制
【1】read()
从缓冲区读取一个字符
【2】read(byte[] b, int off, int len)
将最多len 个数据字符从缓冲区off位置开始读入 b数组。
【3】readLine
从缓冲区一次读取一行字符,返回字符串

5.2.1.5.1 LineNumberReader

(1)作用
LineNumberReader继承自BufferedReader,提供了获取和设置行号的方法
特点和常用方法基本和BufferedReader一样只是换行的时候会统计当前第几行

5.2.1.6 FilterReader

过滤器字符输入流,这里用到了装饰器模式,它的主要用途在于给一个对象动态的添加功能。FilterReader仅仅是对Reader中所有方法进行了重写,并且只是调用传入的Reader子类的方法,话句话说就是没有对传入的低级字符输入流进行任何的装饰,它们的作用是为所有字符输入流的装饰类提供一个标准、一个类似于接口的作用,具体的装饰功能由FilterReader的子类来完成

5.2.1.6.1 PushbackReader

(1)主要作用
常情况下我们从流中读取数据时都是顺序操作的,也许流中的数据并不都是我们需要的,按照平常的流,我们要做的是就是将流中的数据依读取取出,并对取出的数据进行筛选,不符合条件的数据就丢弃。PushbackReader流则稍有不同,它通过内部的一个缓存从而支持了数据的回推,在上述场景下,当遇到不需要的数据时,PushbackReader还可以将数据重新推回到流中,其实只是保存在缓冲区,下次读取的时候优先读取缓冲区,再读取里面的流
(2)特点
【1】输入流
【2】字符流
【3】处理流,数据源其他节点流
【4】操作其他节点流
【5】包含缓冲区
仅仅保存推回的字节,并且这个字节数组是从后往前写入的,先写下标大的

(3)常用方法
【1】read()
每次读取一个字符的数据。从方法中可以看出,优先读取回推缓存中的数据,如果回推缓存中没有数据,那么就正常调用底层Reader对应的read方法
【2】read(char [] b, int off, int len)
一次读取多个字符的read方法,其包含三个参数,第一个为承载读取的数据的字符数组,第二个参数为从数组的哪个位置开始存储数据,第三个参数则是要进行存储的数据长度。
【3】unread(int b)
一次回推一个字符数据到缓冲区
【4】unread(char[] b, int off, int len)
一次可以回推多个字符数据,第一个参数为一个char型数组,用于存放所要进行回推操作的数据,第二和第三个参数都是一个int型数值,分别代表从传入的数组中取出数据的起点,以及其需要回推的数据长度。
【5】unread(byte[] b)
一次可以回推多个字符数据的unread方法,将传入的数组的所有数据都回推到内置缓存中去

5.2.2 Writer

5.2.2.1 CharArrayWriter

(1)作用
主要是用来写入字符数组
(2)特点
【1】输出流
【2】字符流
【3】节点流,数据源一般是字符数组
【4】操作字符数组
【5】包含缓冲区

(3)常用方法
底层用来一个字符数组来保存数据,也就是内部缓冲区,方法用synchronize加锁
核心方法,Override(重写)了抽象类Writer的write方法:
【1】write(int a)
作用是写入1个字符数据到字符流(缓冲区)
【2】write(charb[], int off, int len)
作用是将字符数组b的数据写入到字符流(缓冲区)。off是将字符数组b的起始位置,length是写入的字符的长度

5.2.2.2 OutputStreamWriter

(1)作用
字节流通向字符流的桥梁。底层使用StreamEncoder对输入字节流进行包装,从输出流写入到字符数组,然后利用CharSetDecoder进行编码
(2)特点
【1】输出流
【2】字符流
【3】处理流,数据源一般是字节流
【4】操作字节流

(3)常用方法
【1】write()
写一个字符到输出流

【2】read(char cbuf[], int offset, int length)
从字符数组b中取数据,从off开始的位置,len是写入的长度,然后将这些取到的数据写入输出流

5.2.2.2.1 FileWriter

(1)作用
包装FileOutputStream,然后基本都是集成了父类OutputStreamWriter的方法,
特点和常用方法也和OutputStreamWriter一样

5.2.2.3 StringWriter

(1)作用
写入字符串的内容
(2)特点
【1】输出流
【2】字符流
【3】节点流,数据源就是字符串
【4】操作字符串
【5】包含StringBuffer,其实是字符数组

(3)常用方法
【1】write(int c)
从输出流中写入一个字符到缓冲
【2】read(char[] b, int off, int len)
将最多 len 个数据字节从此输出流写入 到缓冲。

5.2.2.4 PipedWriter

(1)作用
内部使用字符数组,也就是缓冲区,也就是管道大小,它们的作用是让多线程可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedWriter和PipedReader配套使用。使用管道通信时,大致的流程是:我们在线程A中向PipedWriter中写入数据,这些数据会自动的发送到与PipedWriter对应的PipedReader中,进而存储在PipedWriter的缓冲中;此时,线程B通过读取PipedReader中的数据。就可以实现,线程A和线程B的通信。

(2)特点
【1】输出流
【2】字符流
【3】节点流,数据源一般是管道,管道本质是一个字符数组
【4】操作管道
【5】包含缓冲区

(3)常用方法
【1】write(int b)
底层调用输入流的receive方法,往管道(的缓冲)中写入一个字符
【2】write(char b[], int off, int len)
底层调用输入流的receive方法,往管道(的缓冲)中写入字符数组b从off位置开始len长的字符数据
【3】connect
连接输入流

5.2.2.5 BufferedWriter

(1)作用
提供了经过测试的缓冲数组,默认8k,减少对磁盘的访问来提高写入速度,当然底层也是用了节点流的write(char[] b, int off, int len),只是它帮我们写好了并且提供了很多其他的操作
(2)特点
【1】输出流
【2】字符流
【3】处理流,数据源其他节点流
【4】操作其他节点流
【5】包含缓冲区

(3)常用方法
用到了synchronized同步锁机制和cas乐观锁机制
【1】write()
写入一个字符到缓冲区
【2】write(byte[] b, int off, int len)
将字符数组b从off位置开始的最多len 个数据字符写入缓冲区

5.2.2.6 FilterWriter

过滤器字符输出流,这里用到了装饰器模式,它的主要用途在于给一个对象动态的添加功能。FilterWriter仅仅是对Writer中所有方法进行了重写,并且只是调用传入的Writer子类的方法,话句话说就是没有对传入的低级字符输出流进行任何的装饰,它们的作用是为所有字符输出流的装饰类提供一个标准、一个类似于接口的作用,具体的装饰功能由FilterWriter的子类来完成

5.2.2.7 PrintWriter

(1)作用
是用来装饰其它输出流,方便地打印各种数据值表示形式

(2)特点
【1】输出流
【2】字符流
【3】处理流,数据源其他节点流
【4】操作其他节点流

(3)常用方法

【1】append(char c)
将“字符c”追加到“PrintWriter输出流中”
【2】append(CharSequence charSequence, int start, int end)
将“字符序列从start(包括)到end(不包括)的全部字符”追加到“PrintWriter输出流中”
【3】append(CharSequence charSequence)
将“字符序列的全部字符”追加到“PrintWriter输出流中”
【4】format(Locale l, String format, Object… args)
根据“Locale值(区域属性)”来格式化数据
【5】format(String format, Object… args)
根据“默认的Locale值(区域属性)”来格式化数据
【6】print(float f)
将“float数据f对应的字符串”写入到“PrintWriter输出流”中,print实际调用的是write函数
【7】print(double d)
将“double数据d对应的字符串”写入到“PrintWriter输出流”中,print实际调用的是write函数
【8】print(String str)
将“字符串数据str”写入到“PrintWriter输出流”中,print实际调用的是write函数
【9】print(Object o)
将“对象o对应的字符串”写入到“PrintWriter输出流”中,print实际调用的是write函数
【10】print(char c)
将“字符c对应的字符串”写入到“PrintWriter输出流”中,print实际调用的是write函数
【11】print(char[] chars)
将“字符数组chars对应的字符串”写入到“PrintWriter输出流”中,print实际调用的是write函数
【12】print(long l)
将“long型数据l对应的字符串”写入到“PrintWriter输出流”中,print实际调用的是write函数
【13】print(int i)
将“int数据i对应的字符串”写入到“PrintWriter输出流”中,print实际调用的是write函数
【14】print(boolean b)
将“boolean数据b对应的字符串”写入到“PrintWriter输出流”中,print实际调用的是write函数
【15】printf(Locale l, String format, Object… args)
将“数据args”根据“Locale值(区域属性)”按照format格式化,并写入到“PrintWriter输出流”中
【16】printf(String format, Object… args)
将“数据args”根据“默认Locale值(区域属性)”按照format格式化,并写入到“PrintWriter输出流”中
【17】println()
将“换行符”写入到“PrintWriter输出流”中,println实际调用的是write函数
【18】println(float f)
将“float数据对应的字符串+换行符”写入到“PrintWriter输出流”中,println实际调用的是write函数
【19】println(int i)
将“int数据对应的字符串+换行符”写入到“PrintWriter输出流”中,println实际调用的是write函数
【20】println(long l)
将“long数据对应的字符串+换行符”写入到“PrintWriter输出流”中,println实际调用的是write函数
【21】println(Object o)
将“对象o对应的字符串+换行符”写入到“PrintWriter输出流”中,println实际调用的是write函数
【22】println(char[] chars)
将“字符数组chars对应的字符串+换行符”写入到“PrintWriter输出流”中,println实际调用的是write函数
【23】println(String str)
将“字符串str+换行符”写入到“PrintWriter输出流”中,println实际调用的是write函数
【24】println(char c)
将“字符c对应的字符串+换行符”写入到“PrintWriter输出流”中,println实际调用的是write函数
【25】println(double d)
将“double数据对应的字符串+换行符”写入到“PrintWriter输出流”中,println实际调用的是write函数
【26】println(boolean b)
将“boolean数据对应的字符串+换行符”写入到“PrintWriter输出流”中,println实际调用的是write函数
【27】write(int c)
将数据c写入到“PrintWriter输出流”中。c虽然是int类型,但实际只会写入2个字节
【28】write(char[] buffer, int offset, int length)
将“buffer中从offset开始的length个字符”写入到“PrintWriter输出流”中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java封神之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值