IO流(二)
IO流-字符流
FileReader(文件字符输入流)
作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。
| 构造器 |
说明 |
| public FileReader(File file) |
创建字符输入流管道与源文件接通 |
| public FileReader(String pathname) |
创建字符输入流管道与源文件接通 |
| 方法名称 |
说明 |
| public int read() |
每次读取一个字符返回,如果发现没有数据可读会返回-1. |
| public int read(char[] buffer) |
每次用一个字符数组去读取数据,返回字符数组读取了多少个字符,如果发现没有数据可读会返回-1. |
示例
try (
Reader fr = new FileReader("C:/...");
) {
char[] buffer = new char[3];
int len;
while ((len = fr.read(buffer)) != -1) {
System.out.print(new String(guffer, 0 ,len));
}
} catch (Exception e) {
e.printStackTrace();
}
FileWriter(文件字符输出流)
作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。
| 构造器 |
说明 |
| public FileWriter(File file) |
创建字节输出流管道与源文件对象接通 |
| public FileWriter(String filepath) |
创建字节输出流管道与源文件路径接通 |
| public FileWriter(File file,boolean append) |
创建字节输出流管道与源文件对象接通,可追加数据 |
| public FileWriter(String filepath,boolean append) |
创建字节输出流管道与源文件路径接通,可追加数据 |
| 方法名称 |
说明 |
| void write(int c) |
写一个字符 |
| void write(String str) |
写一个字符串 |
| void write(String str, int off, int len) |
写一个字符串的一部分 |
| void write(char[] cbuf) |
写入一个字符数组 |
| void write(char[] cbuf, int off, int len) |
写入字符数组的一部分 |
字符输出流使用时的注意事项
字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效。
| 方法名称 |
说明 |
| public void flush() throws IOException |
刷新流,就是将内存中缓存的数据立即写到文件中去生效 |
| public void close() throws IOException |
关闭流的操作,包含了刷新 |
字节流、字符流的使用场景小结
- 字节流适合做一切文件数据的拷贝(音视频,文本);字节流不适合读取中文内容输出。
- 字符流适合做文本文件的操作(读,写)。
IO流-缓冲流
IO流的体系
- FileInputStream、FileOutputSteam、FileReader和FileWriter被称为原始流/低级流。
- BufferedInputStream、BufferedOutputStream、BufferedReader和BufferedWriter被称为包装流/处理流。
- 包装流的作用是对原始流进行包装,以提高原始流读写数据的性能。
字节缓冲流
- 作用:提高字节流读写数据的性能。
- 原理:字节缓冲输入流自带了8KB缓冲池;字节缓冲输出流也自带了8KB缓冲池。
| 构造器 |
说明 |
| public BufferedInputStream(InputStream is) |
把低级的字节输入流包装成一个高级的缓冲字节输入流,从而提高读数据的性能 |
| public BufferedOutputStream(OutputStream os) |
把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能 |
字符缓冲流
BufferedReader(字符缓冲输入流)
作用:自带8K(8192)的字符缓冲池,可以提高字符输入流读取字符数据的性能。
| 构造器 |
说明 |
| public BufferedReader(Reader r) |
把低级的字符输入流包装成字符缓冲输入流管道,从而提高字符输入流读字符数据的性能 |
| 方法 |
说明 |
| public String readLine() |
读取一行数据返回,如果没有数据可读了,会返回null |
BufferedWriter(字符缓冲输出流)
作用:自带8K的字符缓冲池,可以提高字符输出流写字符数据的性能。
| 构造器 |
说明 |
| public BufferedWriter(Writer r) |
把低级的字符输出流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能 |
| 方法 |
说明 |
| public void newLine() |
换行 |
原始流、缓冲流的性能分析
| 方式 |
性能 |
| 文件字节流结合单个字节复制文件 |
非常慢 |
| 文件字节流结合字节数组复制文件 |
快 |
| 字节缓冲流结合单个字节复制文件 |
比较慢 |
| 字节缓冲流结合字节数组复制文件 |
快 |
- 建议使用字节缓冲输入流、字节缓冲输出流,结合字节数组的方式,目前来看是性能最优的组合。
IO-转换流
不同编码读取出现乱码的问题
IO流的体系
- 解决不同编码时,字符流读取文本内容乱码的问题。
- 解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
| 构造器 |
说明 |
| public InputStreamReader(InputStream is) |
把原始的字节输入流,按照代码默认编码转成字符输入流(与直接用FileReader的效果一样) |
| public InputStreamReader(InputStream is,String charset) |
把原始的字节输入流,按照指定字符集编码转成字符输入流(重点) |
控制写出去的字符使用什么字符集编码的方法
- 调用String提供的getBytes方法解决。
String data = "我爱你中国abc";
byte[] bytes = data.getBytes("GBK");
- 使用”字符输出转换流”实现。
OutputStreamWriter字符输出转换流
作用:可以控制写出去的字符使用什么字符集编码。
解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了。
| 构造器 |
说明 |
| public OutputStreamWriter(OutputStream os) |
可以把原始的字节输出流,按照代码默认编码转换成字符输出流。 |
| public OutputStreamWriter(OutputStream os,String charset) |
可以把原始的字节输出流,按照指定编码转换成字符输出流(重点) |
IO流-打印流
IO流的体系
PrintStream/PrintWriter(打印流)
作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。
PrintStream提供的打印数据的方案
| 构造器 |
说明 |
| public PrintStream(OutputStream/File/String) |
打印流直接通向字节输出流/文件/文件路径 |
| public PrintStream(String fileName, Charset charset) |
可以指定写出去的字符编码 |
| public PrintStream(OutputStream out, boolean autoFlush) |
可以指定实现自动刷新 |
| public PrintStream(OutputStream out, boolean autoFlush, String encoding) |
可以指定实现自动刷新,并可指定字符的编码 |
| 方法 |
说明 |
| public void println(Xxx xx) |
打印任意类型的数据出去 |
| public void write(int/byte[]/byte[]一部分) |
可以支持写字节数据出去 |
PrintWriter提供的打印数据的方案
| 构造器 |
说明 |
| public PrintWriter(OutputStream/Writer/File/String) |
打印流直接通向字节输出流/文件/文件路径 |
| public PrintWriter(String fileName, Charset charset) |
可以指定写出去的字符编码 |
| public PrintWriter(OutputStream out/Writer, boolean autoFlush) |
可以指定实现自动刷新 |
| public PrintWriter(OutputStream out, boolean autoFlush, String encoding) |
可以指定实现自动刷新,并可指定字符的编码 |
| 方法 |
说明 |
| public void println(Xxx xx) |
打印任意类型的数据出去 |
| public void write(int/String/char[]/String或char[]的一部分) |
可以支持写字符数据出去 |
PrintStream和PrintWriter的区别
- 打印数据的功能上是一模一样的:都是使用方便,性能高效(核心优势)。
- PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。
- PrintWriter继承自字符输出流Writer,因此支持写字符数据出去。
打印流的应用:输出语句重定向
可以用下方代码把输出语句的打印位置改到某个文件中去。
PrintStream ps = new PrintStream("文件地址");
System.setOut(ps);
IO流-数据流
IO流的体系
DataOutputStream(数据输出流)
允许把数据和其类型一并写出去。
| 构造器 |
说明 |
| public DataOutputStream(OutputStream out) |
创建新数据输出流包装基础的字节输出流 |
| 方法 |
说明 |
| public final void writeByte(int v) throws IOException |
将byte类型的数据写入基础的字节输出流 |
| public final void writeInt(int v) throws IOException |
将int类型的数据写入基础的字节输出流 |
| public final void writeDouble(Double v) throws IOException |
将double类型的数据写入基础的字节输出流 |
| public final void writeUTF(String str) throws IOException |
将字符串数据以UTF-8编码成字节写入基础的字节输出流 |
| public void write(int/byte[]/byte[]一部分) |
支持写字节数据出去 |
用于读取数据输出流写出去的数据。
| 构造器 |
说明 |
| public DataInputStream(InputStream is) |
创建新数据输入流包装基础的字节输入流 |
| 方法 |
说明 |
| Public final byte readByte() throws IOException |
读取字节数据返回 |
| public final int readInt() throws IOException |
读取int类型的数据返回 |
| public final double readDouble() throws IOException |
读取double类型的数据返回 |
| public final String readUTF() throws IOException |
读取字符串(UTF-8)数据返回 |
| public int read(byte[]) |
支持读字节数据进来 |
注意
使用数据输入流读取时,数据类型的顺序必须与使用数据输出流写入时的顺序一致。
IO流-序列化流
序列化
对象序列化:把Java对象写入到文件里。
对象反序列化:把文件里的Java对象读出来。
IO流的体系
ObjectOutputStream(对象字节输出流)
可以把Java对象进行序列化:把Java对象存入到文件中去。
| 构造器 |
说明 |
| public ObjectOutputStream(OutputStream out) |
创建对象字节输出流,包装基础的字节输出流 |
| 方法 |
说明 |
| public final void writeObject(Object o) throws IOException |
把对象写出去 |
注意:对象如果要参与序列化,必须实现序列化接口(java.io.Serializable)。
可以把Java对象进行反序列化:把存储在文件中的Java对象读入到内存中来。
| 构造器 |
说明 |
| public ObjectInputStream(InputStream is) |
创建对象字节输入流,包装基础的字节输入流 |
| 方法 |
说明 |
| public final Object readObject() |
把存储在文件中的Java对象读出来 |
几点注意
- 用一个ArrayList集合存储多个对象,然后直接对集合进行序列化即可
注意:ArrayList集合已经实现了序列化接口。
- 如果某个成员变量不需要参与序列化,那么在这个成员变量前加上
transient修饰符即可。
补充知识:IO框架
什么是框架
- 为了解决某类问题编写的一套类、接口等,可以理解成一个半成品,大多框架都是第三方研发的。
- 好处:在框架的基础上开发,可以得到优秀的软件架构,并能提高开发效率。
- 框架的形式:一般是把类、接口等编译成class形式,再压缩成一个.jar结尾的文件发行出去。
什么是IO框架
封装了Java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。
Commons-io
Commons-io是apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率。
| FileUtils类提供的部分方法展示 |
说明 |
| public static void copyFile(File srcFile, File destFile) |
复制文件 |
| public static void copyDirectory(File srcDir, File destDir) |
复制文件夹 |
| public static void deleteDirectory(File directory) |
删除文件夹 |
| public static String readFileToString(File file, String encoding) |
读数据 |
| public static void writeStringToFile(File file, String data, String charsetName, boolean append) |
写数据 |
| IOUtils类提供的部分方法展示 |
说明 |
| public static int copy(InputStream inputStream, OutputStream outputStream) |
复制文件 |
| public static int copy(Reader reader, Writer writer) |
复制文件 |
| public static void write(String data, OutputStream output, String charsetName) |
写数据 |
导入commons-io-2.15.1.jar框架到项目中的步骤
- 在项目中创建一个文件夹:lib。
- 将commons-io-(版本号).jar文件复制到lib文件夹。
- 在jar文件上点右键,选择Add as Library -> 点击OK。
- 在类中导包使用。