简介

FileReader是读取字符流的类,继承于InputStreamReader类,用于将内容通过字符流的方式从文件读取到应用程序中

源码分析

InputStreamReader

InputStreamReader 是字节流通向字符流的桥梁它使用指定的 charset 读取字节并将其解码为字符
它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。 每次调用 InputStreamReader 中的一个 read() 方法**都会导致从底层输入流读取一个或多个字节**。
要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

  1. package java.io;
  2. import java.nio.charset.Charset;
  3. import java.nio.charset.CharsetDecoder;
  4. import sun.nio.cs.StreamDecoder;
  5. /**
  6. * @see BufferedReader
  7. * @see InputStream
  8. * @see java.nio.charset.Charset
  9. *
  10. * @author Mark Reinhold
  11. * @since JDK1.1
  12. */
  13. public class InputStreamReader extends Reader {
  14. // 流解码器,从字节到字符的解码过程严重依赖StreamDecoder类及其方法,通篇都在使用这个类
  15. private final StreamDecoder sd;
  16. /**
  17. * 构造方法,传入一个字节输入流
  18. * @param in An InputStream
  19. */
  20. public InputStreamReader(InputStream in) {
  21. // 调用父类构造方法:Reader(Object lock)
  22. super(in);
  23. try {
  24. // 构建流解码类
  25. sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
  26. } catch (UnsupportedEncodingException e) {
  27. // The default encoding should always be available
  28. throw new Error(e);
  29. }
  30. }
  31. /**
  32. * 构造方法,传入字节输入流以及指定字符集名称(如utf-8)
  33. * @param in
  34. * An InputStream
  35. *
  36. * @param charsetName
  37. * The name of a supported
  38. * {@link java.nio.charset.Charset charset}
  39. */
  40. public InputStreamReader(InputStream in, String charsetName) throws UnsupportedEncodingException
  41. {
  42. super(in);
  43. if (charsetName == null)
  44. throw new NullPointerException("charsetName");
  45. sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
  46. }
  47. /**
  48. * 构造方法,创建使用给定字符集的 InputStreamReader。
  49. * @param in An InputStream
  50. * @param cs A charset
  51. * @since 1.4
  52. * @spec JSR-51
  53. */
  54. public InputStreamReader(InputStream in, Charset cs) {
  55. super(in);
  56. if (cs == null)
  57. throw new NullPointerException("charset");
  58. sd = StreamDecoder.forInputStreamReader(in, this, cs);
  59. }
  60. /**
  61. * 创建使用给定字符集解码器的 InputStreamReader
  62. * @param in An InputStream
  63. * @param dec A charset decoder
  64. *
  65. * @since 1.4
  66. * @spec JSR-51
  67. */
  68. public InputStreamReader(InputStream in, CharsetDecoder dec) {
  69. super(in);
  70. if (dec == null)
  71. throw new NullPointerException("charset decoder");
  72. sd = StreamDecoder.forInputStreamReader(in, this, dec);
  73. }
  74. /**
  75. * 获取此字符流使用的字符编码的名称
  76. * @return The historical name of this encoding, or
  77. * <code>null</code> if the stream has been closed
  78. * @see java.nio.charset.Charset
  79. * @revised 1.4
  80. * @spec JSR-51
  81. */
  82. public String getEncoding() {
  83. return sd.getEncoding();
  84. }
  85. /**
  86. * 读取单个字符
  87. * @return The character read, or -1 if the end of the stream has been
  88. * reached
  89. */
  90. public int read() throws IOException {
  91. return sd.read();
  92. }
  93. /**
  94. * 从流中读入length个字符内容,并插入到字符数组的offset位置后
  95. * 返回读取到的字符个数,返回-1表示到了文件结尾
  96. * @param cbuf Destination buffer 字符数组
  97. * @param offset Offset at which to start storing characters
  98. * @param length Maximum number of characters to read
  99. * @return The number of characters read, or -1 if the end of the
  100. * stream has been reached
  101. */
  102. public int read(char cbuf[], int offset, int length) throws IOException {
  103. return sd.read(cbuf, offset, length);
  104. }
  105. /**
  106. * 是否已经准备好被读取
  107. */
  108. public boolean ready() throws IOException {
  109. return sd.ready();
  110. }
  111. // 关闭字符流,同时关闭解码器
  112. public void close() throws IOException {
  113. sd.close();
  114. }
  115. }

可见,InputStreamReader作为字节流和字符流转换的桥梁,内部通过**StreamDecoder类执行读内容转换的操作**

FileReader

  1. package java.io;
  2. /**
  3. * 文件字符输入流
  4. * @see InputStreamReader
  5. * @see FileInputStream
  6. *
  7. * @author Mark Reinhold
  8. * @since JDK1.1
  9. */
  10. public class FileReader extends InputStreamReader {
  11. /**
  12. * 构造方法,传入文件路径,内部构建了一个文件字节输入流,调用父类构造方法
  13. * @param fileName the name of the file to read from
  14. */
  15. public FileReader(String fileName) throws FileNotFoundException {
  16. super(new FileInputStream(fileName));
  17. }
  18. /**
  19. * 构造方法,传入文件对象,内部构建了一个文件字节输入流,调用父类构造方法
  20. * @param file the <tt>File</tt> to read from
  21. */
  22. public FileReader(File file) throws FileNotFoundException {
  23. super(new FileInputStream(file));
  24. }
  25. /**
  26. * 构造方法,传入文件描述符,内部构建了一个文件字节输入流,调用父类构造方法
  27. * @param fd the FileDescriptor to read from
  28. */
  29. public FileReader(FileDescriptor fd) {
  30. super(new FileInputStream(fd));
  31. }
  32. }

可见,FileReader核心操作都是依赖于父类InputStreamReader的方法去执行的

简单使用

现有一文件如下:
图片.png

  1. package com.java.io;
  2. import java.io.FileNotFoundException;
  3. import java.io.FileReader;
  4. import java.io.IOException;
  5. import java.util.Arrays;
  6. /**
  7. * @description FileReader 示例
  8. * @date: 2021-01-18 22:45
  9. */
  10. public class FileReaderExample {
  11. public static void main(String[] args) {
  12. commonExample();
  13. }
  14. public static void commonExample() {
  15. String filePath = "D:\\IDEAWorkSpace\\JAVALearn\\io\\src\\resource\\file.txt";
  16. FileReader fileReader = null;
  17. try {
  18. fileReader = new FileReader(filePath);
  19. // 如果文件字符流已准备好
  20. if(fileReader.ready()){
  21. char[] contents = new char[30];
  22. int read = fileReader.read(contents); // 读取内容到contents数组
  23. System.out.println("读取到了"+read+"个字符");
  24. System.out.print("读取到的内容:");
  25. for(int i=0;i<contents.length;i++){
  26. // 如遇\0表示为空
  27. if(contents[i] == '\0'){
  28. break;
  29. }
  30. System.out.print(contents[i]+",");
  31. }
  32. }
  33. } catch (FileNotFoundException e) {
  34. e.printStackTrace();
  35. } catch (IOException e) {
  36. e.printStackTrace();
  37. }finally {
  38. if(null != fileReader){
  39. try {
  40. fileReader.close();
  41. } catch (IOException e) {
  42. e.printStackTrace();
  43. }
  44. }
  45. }
  46. }
  47. }

输出结果:

  1. 读取到了23个字符
  2. 读取到的内容:拜, ,拜, ,我, ,的, ,乖, ,乖, ,隆, ,地, ,动, ,!, ,!, ,!

总结

1、FileReader是读取字符流的类,继承于InputStreamReader类,用于将内容通过字符流的方式从文件读取到应用程序中

2、
InputStreamReader 是字节流通向字符流的桥梁它使用指定的 charset 读取字节并将其解码为字符
它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
每次调用 InputStreamReader 中的一个 read() 方法**都会导致从底层输入流读取一个或多个字节

3、InputStreamReader作为字节流和字符流转换的桥梁,内部通过**StreamDecoder类执行读内容转换的操作

4、FileReader核心操作都是依赖于父类InputStreamReader的方法去执行的