一. 概述
Reader是一个抽象类,继承自Readable接口、Closeable接口;
它是一个字符输入流,具体实现的子类如下图
image.png
二. 类定义的方法
object lock // lock是作为synchronized同步锁的,只有获取到这个lock对象才能执行某些函数
public int read() throws IOException
public int read(char cbuf[]) throws IOException
abstract public int read(char cbuf[], int off, int len) throws IOException
public long skip(long n) throws IOException
skip和三个read方法本质上都是调用int read(char cbuf[], int off, int len) 方法来实现的
调用该方法会产生阻塞直到1)遇到流的尾部返回-1、2)有数据可以读入、3)抛出异常
public boolean ready() throws IOException // 输入流是否已经就绪可读了
public boolean markSupported()
public void mark(int readAheadLimit) throws IOException
public void reset() throws IOException
这三个方法分别是当前流是否支持mark、标记位置、返回到标记的位置
参数readLimit指定这个标记的“有效期“,如果从标记处开始往后,已经获取或者跳过了readLimit个字符,那么这个标记失效,不允许再重新回到这个位置。
abstract public void close() throws IOException // 关闭流
三. InputStreamReader
构造函数
public InputStreamReader(InputStream in)
public InputStreamReader(InputStream in, String charsetName)
public InputStreamReader(InputStream in, Charset cs)
public InputStreamReader(InputStream in, CharsetDecoder dec)
上面的构造函数接受一个InputStream字节输入流和编码格式参数
使用构造函数的两个参数生成一个StreamDecoder sd,后面的字符输入都是通过这个sd来实现的
使用场景和方法
InputStreamReader将InputStream读入的字节流使用指定的字符集转化为字符,并存储到java中
在java代码中使用unicode编码存储具体的字符
image.png
使用示例
try {
FileInputStream fileInputStream = new FileInputStream("E:\\file测试.txt");
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf8");
char[] readArray = new char[100];
inputStreamReader.read(readArray);
log.info("读取的内容={}", Arrays.toString(readArray));
} catch (FileNotFoundException fe) {
log.error("文件不存在异常", fe);
} catch (IOException ie) {
log.error("写入文件发生异常", ie);
}
四. FileReader
构造函数
public FileReader(String fileName) throws FileNotFoundException
public FileReader(File file) throws FileNotFoundException
public FileReader(FileDescriptor fd)
使用场景
FileReader继承自InputStreamReader,也可以实现字节按照指定的编码转化成字符的功能;
FileReader整个类里面都只有构造函数,没有其他内容;构造函数实际上就是把文件参数转化成FileInputStream,然后在调用父类的构造函数。
可以把FileReader看成是固定输入流FileInputStream,固定编码规则UTF8的InputStreamReader。
五. CharArrayReader
构造函数
public CharArrayReader(char buf[])
public CharArrayReader(char buf[], int offset, int length)
内部属性和用法
char buf[] // 所有读取的数据都是来源于这个char数组
int pos // 当前读取到的位置
int count // buf[]数组大小
int markedPos // mark标记位置
CharArrayReader通过构造函数传入一个char buf[],后面所有读取的数据都是来源于这个char数组
CharArrayReader支持mark-reset标记回退功能
使用示例
try {
CharArrayReader charArrayReader = new CharArrayReader("这是个垃圾的国家".toCharArray());
// 标记位置
charArrayReader.mark(20);
char[] readArray = new char[4];
charArrayReader.read(readArray);
log.info("读取的内容={}", Arrays.toString(readArray));
// 恢复到标记位置
charArrayReader.reset();
} catch (IOException ie) {
log.error("写入文件发生异常", ie);
}
六. BufferedReader
构造函数
public BufferedReader(Reader in, int sz)
public BufferedReader(Reader in)
使用场景
BufferedReader为构造函数中的Reader in字符输出流提供了缓冲功能,具体是通过内部属性char cb[]数组缓冲来实现的;
当读取数据量少时,直接从cb[]缓冲数组中读取数据;当缓冲数组中数据读取完了之后在从Reader in字符输入流中读取数据填充这个缓冲数组cb[];
BufferedReader提供了mark-reset功能;
BufferedReader提供了按行读取readLine()功能;BufferedReader的readLine()是一个阻塞函数,当没有数据读取时就会一直阻塞在那而不是返回null,直到这个函数读取到新的数据才会继续往下执行。这个方法只要读到流结束或者流关闭,就会返回null。
使用示例
try {
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("E:\\file测试.txt"));
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// 读取文件内容到数组中
char[] readArray = new char[4];
bufferedReader.read(readArray);
log.info("读取的内容={}", Arrays.toString(readArray));
// 标记位置
bufferedReader.mark(20);
// 读取一行数据
String data = bufferedReader.readLine();
log.info("读取的内容={}", data.length());
// 恢复到标记位置
bufferedReader.reset();
} catch (FileNotFoundException fe) {
log.error("文件不存在异常", fe);
} catch (IOException ie) {
log.error("读文件发生异常", ie);
}
七. PushbackReader
类的功能
PushbackReader是一个使用装饰器模式增强了功能的字符输入流,它没有对应具体的流,而是对构造函数传入的具体的流增加了回退功能;
PushbackReader本质上是通过一个内部缓冲区数组char[] buf实现的。从PushbackReader读出数据后,只要缓冲区数组char[] buf没有满,就可以使用unread()将数据退回到buf数组中。
读取数据时,如果char[] buf回退缓冲区有数据,则优先从char[] buf回退缓冲区读取。
构造函数
public PushbackReader(Reader in, int size)
public PushbackReader(Reader in)
使用示例
try {
FileInputStream fileInputStream = new FileInputStream("E:\\file测试.txt");
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf8");
PushbackReader pushbackReader = new PushbackReader(inputStreamReader, 4);
char[] readArray = new char[4];
pushbackReader.read(readArray);
log.info("读取的内容={}", Arrays.toString(readArray));
pushbackReader.unread(readArray);
} catch (FileNotFoundException fe) {
log.error("文件不存在异常", fe);
} catch (IOException ie) {
log.error("读文件发生异常", ie);
}
八. 其他子类
PipedReader
PipedWriter和PipedReader必须配合一起使用,用于线程之间的管道通信。
PipedReader中有一个缓冲区char buffer[]可以用于保存数据;
PipedReader和PipedWriter操作的都是这个缓冲区,PipedReader操作的自己的缓冲区,PipedWriter操作的是PipedReader的缓冲区
PipedWriter需要和PipedReader进行连接,或者在构造的时候直接连接;连接之后,就形成了一个管道。
StringReader
StringReader用法和CharArrayReader类似,都是从内部属性中读取字符,只不过CharArrayReader是从内部char buf[]读取字符,而StringReader是从内部String str读取字符。