Java IO 学习总结(一)输入流/输出流
Java IO 学习总结(二)File 类
Java IO 学习总结(三)BufferedInputStream
Java IO 学习总结(四)BufferedReader 缓冲字符流
Java IO 学习总结(五)OutputStreamWriter
前言
学习IO流,记录并分享。文章如有错误,恳请指正。
类图
1、什么是 OutputStreamWriter?
OutputStreamWriter是字符通向字节流的桥梁:可以指定的charset将要写入流中的字符编码成字节。(编码:能看懂的字符变为看不懂的字节),关于java当中转换流,OutputStreamWriter的使用,主要是通过指定的编码表名称,来查询相对应的编码表,将字符编码为字节存储到缓冲区,再使用flush方法将内存中的文件刷新带文件中。
2、为什么要使用 OutputStreamWriter?
计算机中任何数据都是二进制储存的,不管是文本、图片还是视频,所以我们可以用字节流对所有数据进行操作,但是有时候我们又想用字符流更加便捷的操作,这个时候我们就要用到转换流了。
下面举个例子说明一下:
比方说,我们现在要读取一张相片的数据,这个时候我们应该选择用字节输入流,这样我们获得的数据就是字节的形式但是在程序中我们并不想以字节的形式储存,所以这个时候我们就需要将其转换成字符流,从而保存在字符串数组中。这里就用到InputStreamReader类,将“输入字节流”转换成“字符输入流”。同理可以理解OutputStreamWriter类的作用。
3、OutputStreamWriter 的构造函数源码
/**
* Creates an OutputStreamWriter that uses the named charset.
*
* @param out
* An OutputStream
*
* @param charsetName
* The name of a supported
* {@link java.nio.charset.Charset charset}
*
* @exception UnsupportedEncodingException
* If the named encoding is not supported
*/
public OutputStreamWriter(OutputStream out, String charsetName)
throws UnsupportedEncodingException
{
super(out);
if (charsetName == null)
throw new NullPointerException("charsetName");
se = StreamEncoder.forOutputStreamWriter(out, this, charsetName);
}
/**
* Creates an OutputStreamWriter that uses the default character encoding.
*
* @param out An OutputStream
*/
public OutputStreamWriter(OutputStream out) {
super(out);
try {
se = StreamEncoder.forOutputStreamWriter(out, this, (String)null);
} catch (UnsupportedEncodingException e) {
throw new Error(e);
}
}
/**
* Creates an OutputStreamWriter that uses the given charset.
*
* @param out
* An OutputStream
*
* @param cs
* A charset
*
* @since 1.4
* @spec JSR-51
*/
public OutputStreamWriter(OutputStream out, Charset cs) {
super(out);
if (cs == null)
throw new NullPointerException("charset");
se = StreamEncoder.forOutputStreamWriter(out, this, cs);
}
/**
* Creates an OutputStreamWriter that uses the given charset encoder.
*
* @param out
* An OutputStream
*
* @param enc
* A charset encoder
*
* @since 1.4
* @spec JSR-51
*/
public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
super(out);
if (enc == null)
throw new NullPointerException("charset encoder");
se = StreamEncoder.forOutputStreamWriter(out, this, enc);
简单介绍:
public OutputStreamWriter(OutputStream out, String charsetName); // 创建使用指定字符集的 OutputStreamWriter。
public OutputStreamWriter(OutputStream out); // 创建使用默认字符编码(UTF-8)的 OutputStreamWriter
public OutputStreamWriter(OutputStream out, Charset cs); // 创建使用给定字符集的 OutputStreamWriter
public OutputStreamWriter(OutputStream out, CharsetEncoder enc); // 创建使用给定字符集编码器的 OutputStreamWriter。
4、OutputStreamWriter 的公共方法
public String getEncoding(); // 获取当前使用的字符编码集
void flushBuffer() throws IOException; // 在构造时设置缓冲区的大小(默认8192),当调用write时发现缓冲区剩余空间不足以写入或者调用flush()方法时,则调用flushBuffer方法使用基础流将数据写入。
public void write(int c) throws IOException; // 要写入的字符
public void write(char cbuf[], int off, int len) throws IOException; // 要写入的字符数组
public void write(String str, int off, int len) throws IOException; // 要写入的字符串
public void flush() throws IOException; // 将缓存区的数据刷到磁盘中
public void close() throws IOException; // 关闭该流并释放与之关联的所有资源。
重点记录下 close()这个方法:
一般情况下,数据写入缓存区后,需要使用 flush() 方法将数据刷入到硬盘中,但据我查看源码与实践发现,close()这个方法的底层实现有调用 flush() 这个方法 ,将数据刷到磁盘中,所以在你显示调用 close() 来关闭流时,可以不显示调用 flush() 这个方法。
源码如下:
// OutputStreamWriter 内部注入了 StreamEncoder 对象,close 底层实际调用的是 StreamEncoder 的 close() 方法
public class OutputStreamWriter extends Writer {
private final StreamEncoder se;
public void close() throws IOException {
se.close();
}
}
// StreamEncoder
public class StreamEncoder extends Writer {
public void close() throws IOException {
synchronized(this.lock) {
if (this.isOpen) {
this.implClose();
this.isOpen = false;
}
}
}
void implClose() throws IOException {
this.flushLeftoverChar((CharBuffer)null, true);
try {
while(true) {
CoderResult var1 = this.encoder.flush(this.bb);
if (var1.isUnderflow()) {
if (this.bb.position() > 0) {
this.writeBytes();
}
if (this.ch != null) {
this.ch.close();
} else {
this.out.close();
}
return;
}
if (var1.isOverflow()) {
assert this.bb.position() > 0;
this.writeBytes();
} else {
var1.throwException();
}
}
} catch (IOException var2) {
this.encoder.reset();
throw var2;
}
}
}
5、实战
- 使用 InputStreamReader 读取磁盘中 txt 文件内容:
/**
* 使用 InputStreamReader 读取磁盘中 txt 文件内容
* <p>
* throws IOException 读取文件与关闭流的时候可能会抛出这个异常
*/
public static void readTxt() {
// 文件路径
String filePath = "D:/test/gls.txt";
FileInputStream fileInputStream = null;
InputStreamReader inputStreamReader = null;
try {
fileInputStream = new FileInputStream(filePath);
// 可以不指定字符编码集, 默认 UTF-8
inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
// 创建一个长度为 1024 大小的 char 数组
char chars[] = new char[1024];
// 将字节数据读入 chars 数组中。
int read = inputStreamReader.read(chars);
// 打印到控制台
System.out.println(new String(chars, 0, read));
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inputStreamReader != null) {
inputStreamReader.close();
System.out.println("inputStreamReader 关闭该流并释放与之关联的所有资源。");
}
if (fileInputStream != null) {
fileInputStream.close();
System.out.println("fileInputStream 关闭该流并释放与之关联的所有资源。");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 向指定 txt 文件中写入内容
/**
* 向 txt 文件中写入指定内容, 如果文件不存在, 会创建文件,不会抛出异常。
* 但如果文件存在, 写入的内容会覆盖原文件中已有的内容,请谨慎操作!
* <p>
* throws IOException 读取文件与关闭流的时候可能会抛出这个异常
*/
private static void writerTxt() {
// 文件路径
String filePath = "D:/test/gle.txt";
// 要写入的内容
String content = "滚水看不到倒影,盛怒看不到真相。";
FileOutputStream fileOutputStream = null;
OutputStreamWriter outputStreamWriter = null;
try {
fileOutputStream = new FileOutputStream(filePath);
outputStreamWriter = new OutputStreamWriter(fileOutputStream);
// 将字符串写入到文件中, 写入指定长度的内容
outputStreamWriter.write(content, 0, content.length());
// 使用 flush 方法将内存中的文件刷新到文件中
// 该方法在 close() 方法的底层中有调用,不显示调用也可以
outputStreamWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (outputStreamWriter != null) {
outputStreamWriter.close();
System.out.println("outputStreamWriter 关闭该流并释放与之关联的所有资源。");
}
if (fileOutputStream != null) {
fileOutputStream.close();
System.out.println("fileOutputStream 关闭该流并释放与之关联的所有资源。");
}
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("执行成功");
}
Java IO 学习总结(六) 正在完善中,后续更新~