简介
FileReader是读取字符流的类,继承于InputStreamReader类,用于将内容通过字符流的方式从文件读取到应用程序中
源码分析
InputStreamReader
InputStreamReader 是字节流通向字符流的桥梁,它使用指定的 charset 读取字节并将其解码为字符。
它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。 每次调用 InputStreamReader 中的一个 read() 方法**都会导致从底层输入流读取一个或多个字节**。
要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
package java.io;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import sun.nio.cs.StreamDecoder;
/**
* @see BufferedReader
* @see InputStream
* @see java.nio.charset.Charset
*
* @author Mark Reinhold
* @since JDK1.1
*/
public class InputStreamReader extends Reader {
// 流解码器,从字节到字符的解码过程严重依赖StreamDecoder类及其方法,通篇都在使用这个类
private final StreamDecoder sd;
/**
* 构造方法,传入一个字节输入流
* @param in An InputStream
*/
public InputStreamReader(InputStream in) {
// 调用父类构造方法:Reader(Object lock)
super(in);
try {
// 构建流解码类
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
// The default encoding should always be available
throw new Error(e);
}
}
/**
* 构造方法,传入字节输入流以及指定字符集名称(如utf-8)
* @param in
* An InputStream
*
* @param charsetName
* The name of a supported
* {@link java.nio.charset.Charset charset}
*/
public InputStreamReader(InputStream in, String charsetName) throws UnsupportedEncodingException
{
super(in);
if (charsetName == null)
throw new NullPointerException("charsetName");
sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
}
/**
* 构造方法,创建使用给定字符集的 InputStreamReader。
* @param in An InputStream
* @param cs A charset
* @since 1.4
* @spec JSR-51
*/
public InputStreamReader(InputStream in, Charset cs) {
super(in);
if (cs == null)
throw new NullPointerException("charset");
sd = StreamDecoder.forInputStreamReader(in, this, cs);
}
/**
* 创建使用给定字符集解码器的 InputStreamReader
* @param in An InputStream
* @param dec A charset decoder
*
* @since 1.4
* @spec JSR-51
*/
public InputStreamReader(InputStream in, CharsetDecoder dec) {
super(in);
if (dec == null)
throw new NullPointerException("charset decoder");
sd = StreamDecoder.forInputStreamReader(in, this, dec);
}
/**
* 获取此字符流使用的字符编码的名称
* @return The historical name of this encoding, or
* <code>null</code> if the stream has been closed
* @see java.nio.charset.Charset
* @revised 1.4
* @spec JSR-51
*/
public String getEncoding() {
return sd.getEncoding();
}
/**
* 读取单个字符
* @return The character read, or -1 if the end of the stream has been
* reached
*/
public int read() throws IOException {
return sd.read();
}
/**
* 从流中读入length个字符内容,并插入到字符数组的offset位置后
* 返回读取到的字符个数,返回-1表示到了文件结尾
* @param cbuf Destination buffer 字符数组
* @param offset Offset at which to start storing characters
* @param length Maximum number of characters to read
* @return The number of characters read, or -1 if the end of the
* stream has been reached
*/
public int read(char cbuf[], int offset, int length) throws IOException {
return sd.read(cbuf, offset, length);
}
/**
* 是否已经准备好被读取
*/
public boolean ready() throws IOException {
return sd.ready();
}
// 关闭字符流,同时关闭解码器
public void close() throws IOException {
sd.close();
}
}
可见,InputStreamReader作为字节流和字符流转换的桥梁,内部通过**StreamDecoder类执行读内容转换的操作**
FileReader
package java.io;
/**
* 文件字符输入流
* @see InputStreamReader
* @see FileInputStream
*
* @author Mark Reinhold
* @since JDK1.1
*/
public class FileReader extends InputStreamReader {
/**
* 构造方法,传入文件路径,内部构建了一个文件字节输入流,调用父类构造方法
* @param fileName the name of the file to read from
*/
public FileReader(String fileName) throws FileNotFoundException {
super(new FileInputStream(fileName));
}
/**
* 构造方法,传入文件对象,内部构建了一个文件字节输入流,调用父类构造方法
* @param file the <tt>File</tt> to read from
*/
public FileReader(File file) throws FileNotFoundException {
super(new FileInputStream(file));
}
/**
* 构造方法,传入文件描述符,内部构建了一个文件字节输入流,调用父类构造方法
* @param fd the FileDescriptor to read from
*/
public FileReader(FileDescriptor fd) {
super(new FileInputStream(fd));
}
}
可见,FileReader核心操作都是依赖于父类InputStreamReader的方法去执行的。
简单使用
现有一文件如下:
package com.java.io;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
/**
* @description FileReader 示例
* @date: 2021-01-18 22:45
*/
public class FileReaderExample {
public static void main(String[] args) {
commonExample();
}
public static void commonExample() {
String filePath = "D:\\IDEAWorkSpace\\JAVALearn\\io\\src\\resource\\file.txt";
FileReader fileReader = null;
try {
fileReader = new FileReader(filePath);
// 如果文件字符流已准备好
if(fileReader.ready()){
char[] contents = new char[30];
int read = fileReader.read(contents); // 读取内容到contents数组
System.out.println("读取到了"+read+"个字符");
System.out.print("读取到的内容:");
for(int i=0;i<contents.length;i++){
// 如遇\0表示为空
if(contents[i] == '\0'){
break;
}
System.out.print(contents[i]+",");
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null != fileReader){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
输出结果:
读取到了23个字符
读取到的内容:拜, ,拜, ,我, ,的, ,乖, ,乖, ,隆, ,地, ,动, ,!, ,!, ,!
总结
1、FileReader是读取字符流的类,继承于InputStreamReader类,用于将内容通过字符流的方式从文件读取到应用程序中
2、InputStreamReader 是字节流通向字符流的桥梁,它使用指定的 charset 读取字节并将其解码为字符。
它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。 每次调用 InputStreamReader 中的一个 read() 方法**都会导致从底层输入流读取一个或多个字节。
3、InputStreamReader作为字节流和字符流转换的桥梁,内部通过**StreamDecoder类执行读内容转换的操作
4、FileReader核心操作都是依赖于父类InputStreamReader的方法去执行的。