简介

FileWriter是读取字符流的类,继承于OutputStreamWriter类,用于将内容通过字符流的方式从应用程序输出到外部文件中

源码分析

OutputStreamWriter

OutputStreamWriter是字节流通向字符流的桥梁它使用指定的 charset 输出字符并将其编码为字节
它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。 每次调用 OutputStreamWriter 中的一个 writer() 方法**都会导致**在给定字符上调用编码转换器。生成的字节在写入底层输出流之前在缓冲区中累积。
OutputStreamWriter流的作用就是利用字节流作为底层输出流然后构建字符输出流,字符输出流输出字符到流中,然后通过指定的字符集把流中的字符编码成字节输出到字节流中,其作用就是一个桥梁,使得双方链接起来。

  1. /*
  2. * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  3. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  4. *
  5. *
  6. *
  7. *
  8. *
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *
  15. *
  16. *
  17. *
  18. *
  19. *
  20. *
  21. *
  22. *
  23. *
  24. */
  25. package java.io;
  26. import java.nio.charset.Charset;
  27. import java.nio.charset.CharsetEncoder;
  28. import sun.nio.cs.StreamEncoder;
  29. /**
  30. * An OutputStreamWriter is a bridge from character streams to byte streams:
  31. * Characters written to it are encoded into bytes using a specified {@link
  32. * java.nio.charset.Charset charset}. The charset that it uses
  33. * may be specified by name or may be given explicitly, or the platform's
  34. * default charset may be accepted.
  35. *
  36. * <p> Each invocation of a write() method causes the encoding converter to be
  37. * invoked on the given character(s). The resulting bytes are accumulated in a
  38. * buffer before being written to the underlying output stream. The size of
  39. * this buffer may be specified, but by default it is large enough for most
  40. * purposes. Note that the characters passed to the write() methods are not
  41. * buffered.
  42. *
  43. * <p> For top efficiency, consider wrapping an OutputStreamWriter within a
  44. * BufferedWriter so as to avoid frequent converter invocations. For example:
  45. *
  46. * <pre>
  47. * Writer out
  48. * = new BufferedWriter(new OutputStreamWriter(System.out));
  49. * </pre>
  50. *
  51. * <p> A <i>surrogate pair</i> is a character represented by a sequence of two
  52. * <tt>char</tt> values: A <i>high</i> surrogate in the range '&#92;uD800' to
  53. * '&#92;uDBFF' followed by a <i>low</i> surrogate in the range '&#92;uDC00' to
  54. * '&#92;uDFFF'.
  55. *
  56. * <p> A <i>malformed surrogate element</i> is a high surrogate that is not
  57. * followed by a low surrogate or a low surrogate that is not preceded by a
  58. * high surrogate.
  59. *
  60. * <p> This class always replaces malformed surrogate elements and unmappable
  61. * character sequences with the charset's default <i>substitution sequence</i>.
  62. * The {@linkplain java.nio.charset.CharsetEncoder} class should be used when more
  63. * control over the encoding process is required.
  64. *
  65. * @see BufferedWriter
  66. * @see OutputStream
  67. * @see java.nio.charset.Charset
  68. *
  69. * @author Mark Reinhold
  70. * @since JDK1.1
  71. */
  72. public class OutputStreamWriter extends Writer {
  73. // 流编码器
  74. private final StreamEncoder se;
  75. /**
  76. * 构造方法
  77. * @param out
  78. * An OutputStream 字节输出流
  79. *
  80. * @param charsetName
  81. * The name of a supported 字符编码集名称
  82. * {@link java.nio.charset.Charset charset}
  83. *
  84. */
  85. public OutputStreamWriter(OutputStream out, String charsetName)
  86. throws UnsupportedEncodingException
  87. {
  88. super(out);
  89. if (charsetName == null)
  90. throw new NullPointerException("charsetName");
  91. se = StreamEncoder.forOutputStreamWriter(out, this, charsetName);
  92. }
  93. /**
  94. * 构造方法
  95. * @param out An OutputStream 字节输出流
  96. */
  97. public OutputStreamWriter(OutputStream out) {
  98. super(out);
  99. try {
  100. se = StreamEncoder.forOutputStreamWriter(out, this, (String)null);
  101. } catch (UnsupportedEncodingException e) {
  102. throw new Error(e);
  103. }
  104. }
  105. /**
  106. * 构造方法
  107. * @param out
  108. * An OutputStream 字节输出流
  109. *
  110. * @param cs
  111. * A charset 字符编码集
  112. *
  113. * @since 1.4
  114. * @spec JSR-51
  115. */
  116. public OutputStreamWriter(OutputStream out, Charset cs) {
  117. super(out);
  118. if (cs == null)
  119. throw new NullPointerException("charset");
  120. se = StreamEncoder.forOutputStreamWriter(out, this, cs);
  121. }
  122. /**
  123. * 构造方法
  124. * @param out
  125. * An OutputStream 字节输出流
  126. *
  127. * @param enc
  128. * A charset encoder 编码器
  129. * @since 1.4
  130. * @spec JSR-51
  131. */
  132. public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
  133. super(out);
  134. if (enc == null)
  135. throw new NullPointerException("charset encoder");
  136. se = StreamEncoder.forOutputStreamWriter(out, this, enc);
  137. }
  138. /**
  139. * 获取当前流的指定编码名称
  140. * @return The historical name of this encoding, or possibly
  141. * <code>null</code> if the stream has been closed
  142. * @revised 1.4
  143. * @spec JSR-51
  144. */
  145. public String getEncoding() {
  146. return se.getEncoding();
  147. }
  148. /**
  149. * 刷新缓存,将缓存中的数据写入流中
  150. */
  151. void flushBuffer() throws IOException {
  152. se.flushBuffer();
  153. }
  154. /**
  155. * 写入一个字符到流中
  156. */
  157. public void write(int c) throws IOException {
  158. se.write(c);
  159. }
  160. /**
  161. * 将字符数组off位置后的len个元素通过流输出
  162. * @param cbuf Buffer of characters
  163. * @param off Offset from which to start writing characters
  164. * @param len Number of characters to write
  165. *
  166. * @exception IOException If an I/O error occurs
  167. */
  168. public void write(char cbuf[], int off, int len) throws IOException {
  169. se.write(cbuf, off, len);
  170. }
  171. /**
  172. * 将字符串中的off位置后len个字符通过流输出
  173. * @param str A String
  174. * @param off Offset from which to start writing characters
  175. * @param len Number of characters to write
  176. */
  177. public void write(String str, int off, int len) throws IOException {
  178. se.write(str, off, len);
  179. }
  180. /**
  181. * 强刷缓存,将所有缓存中的数据强制输出
  182. * @exception IOException If an I/O error occurs
  183. */
  184. public void flush() throws IOException {
  185. se.flush();
  186. }
  187. /**
  188. * 关闭流,释放资源
  189. */
  190. public void close() throws IOException {
  191. se.close();
  192. }
  193. }

可以看到,OutputStreamWriter构造方法主要是结合一个字节输出流和编码集合构建一个StreamEncoder,该编码器可以将字符编码为字节,而后续所有操作都依赖于该类执行。

FileWriter

package java.io;


/**
 * @see OutputStreamWriter
 * @see FileOutputStream
 *
 * @author      Mark Reinhold
 * @since       JDK1.1
 */
public class FileWriter extends OutputStreamWriter {

    /**
     * 构造方法,传入文件名,构造一个文件字节输出流,调用父类方法构造字符输出流
     *
     * @param fileName  String The system-dependent filename.
     */
    public FileWriter(String fileName) throws IOException {
        super(new FileOutputStream(fileName));
    }

    /**
     * 构造方法,传入文件名和是否追加标识,构造一个文件字节输出流,调用父类方法构造字符输出流
     *
     * @param fileName  String The system-dependent filename.
     * @param append    boolean if <code>true</code>, then data will be written
     *                  to the end of the file rather than the beginning.
     */
    public FileWriter(String fileName, boolean append) throws IOException {
        super(new FileOutputStream(fileName, append));
    }

    /**
     * 构造方法,传入文件对象,构造一个文件字节输出流,调用父类方法构造字符输出流
     *
     * @param file  a File object to write to.
     */
    public FileWriter(File file) throws IOException {
        super(new FileOutputStream(file));
    }

    /**
     * 构造方法,传入文件对象和是否追加标识,构造一个文件字节输出流,调用父类方法构造字符输出流
     * @param file  a File object to write to
     * @param     append    if <code>true</code>, then bytes will be written
     *                      to the end of the file rather than the beginning
     * @since 1.4
     */
    public FileWriter(File file, boolean append) throws IOException {
        super(new FileOutputStream(file, append));
    }

    /**
     * 构造方法,传入文件描述符,构造一个文件字节输出流,调用父类方法构造字符输出流
     * @param fd  FileDescriptor object to write to.
     */
    public FileWriter(FileDescriptor fd) {
        super(new FileOutputStream(fd));
    }
}

可见,FileWriter只提供了三个构造方法,其余所有方法都是依赖于父类OutputStreamWriter执行

简单使用

package com.java.io;

import java.io.FileWriter;
import java.io.IOException;

/**
 * @description
 * @date: 2021-01-19 10:03
 */
public class FileWriterExample {
    public static void main(String[] args) {
        commonExample();
    }

    public static void commonExample() {
        String filePath = "D:\\IDEAWorkSpace\\JAVALearn\\io\\src\\resource\\fileOut.txt";
        FileWriter fileWriter = null;

        try {
            fileWriter = new FileWriter(filePath);

            String message = "只需要看到第五个字符哦";

            fileWriter.write(message, 0, 5);

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null!=fileWriter){
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

文件结果:
图片.png

总结

1、FileWriter是读取字符流的类,继承于OutputStreamWriter类,用于将内容通过字符流的方式从应用程序输出到外部文件中

2、
OutputStreamWriter是字节流通向字符流的桥梁它使用指定的 charset 输出字符并将其编码为字节**。

3、OutputStreamWriter构造方法主要是结合一个字节输出流和编码集合构建一个StreamEncoder,该编码器可以将字符编码为字节,而后续所有操作都依赖于该类执行。

4、FileWriter只提供了三个构造方法,其余所有方法都是依赖于父类OutputStreamWriter执行