IO流(二)
1、字符流
字符流:适合读写文本文件内容。
FileReader(文件字符输入流)
- 作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。



代码演示:
java
public class FileReaderDemo2 {
public static void main(String[] args) {
//目标:文件字符输入流的使用,每次获取多个字符
try(
Reader fr = new FileReader("day10-io-code\\src\\dilei01.txt");
)
{
char[] buffer = new char[3];
int len;
while((len=fr.read(buffer)) !=-1){
String rs = new String(buffer,0,len);
System.out.println(rs);
}
//拓展
// 避免乱码,性能可以,目前读取文本内容的最好方案
}catch( Exception e ){
e.printStackTrace();
}
}
}
2、字符输出流
FileWriter(文件字符输出流)
- 作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。


字符流输出流使用时的注意事项
字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效。


代码演示:
java
public class FileWriteDemo3 {
public static void main(String[] args) throws IOException {
//目标:掌握字符输出流的使用
//1、创建一个文件字符输出流管道与目标文件连通
try(
FileWriter fw = new FileWriter("day10-io-code\\src\\dilei06.txt",true);
){
//2、写字符数据出去
fw.write(97);
fw.write("\r\n");
fw.write('n');
//写字符串
fw.write("This is a file1--");
//写字符串的一部分
fw.write("111我爱你中国",3,3);
//写字符数组
char[] charArray = "ssssaee方的放的".toCharArray();
fw.write(charArray);
//fw.flush();
//fw.close(); 利用了try方法,不需要这些了
}catch(Exception e){
e.printStackTrace();
}
}
}
3、字节缓存流

对原始流进行包装,以提高原始流读写数据的性能。
字节缓冲流的作用
提高字节流读写数据的性能
原理:字节缓冲输入流自带了8kb缓冲池;字节缓冲输出流也自带了8KB缓冲池。


代码演示:
java
//1、创建字节输入流管道与源文件接通
InputStream is = new FileInputStream("D:\\resource\\005.jpg");
//直接使用高级的缓冲字节输入流包装低级的字节输入流
BufferedInputStream bis = new BufferedInputStream(is);
//2、创建字节输出流管道与目标文件连通
OutputStream os = new FileOutputStream("D:\\resource\\009.jpg");
//使用高级的缓冲字节输出流包装低级的字节输出流
BufferedOutputStream bos = new BufferedOutputStream(os);
4、缓冲字符输出流
BufferedReader(字节缓冲输入流)
- 作用:自带8K(8192)的字符缓冲池,可以提高字符输入流读取字符数据的性能。


字符缓冲输入流新增的功能:按照行读取字符

代码演示:
java
public static void main(String[] args) {
//目标:字符缓冲输入流的使用,提升原始字符输入流的读字符性能。多了按照行读取的能力
try(
//1、创建文件字符输入流管道与源文件连通
Reader fr = new FileReader("day10-io-code\\src\\dlei04.txt");
//把低级的字符输入流包装成高级的缓冲字符输入流
BufferedReader br = new BufferedReader(fr);
)
{
//3、缓冲字符输入流多了一个按照行读取内容的功能。(经典代码)
String line;
while((line=br.readLine()) != null){
System.out.println(line);
}
//拓展
// 避免乱码,性能可以,目前读取文本内容的最好方案
}catch( Exception e ){
e.printStackTrace();
}
}
BufferedWriter(字符缓冲输入流)
- 作用:自带8K的字符缓冲池,可以提高字符输出流写字符数据的性能


字符缓冲输出流新增的功能:换行

代码演示:
java
public static void main(String[] args) {
//目标:掌握缓冲字符输出流的使用
//1、创建一个文件字符输出流管道与目标文件连通
try(
FileWriter fw = new FileWriter("day10-io-code\\src\\dilei06.txt",true);
BufferedWriter bw = new BufferedWriter(fw);
){
//2、写字符数据出去
//写字符串
bw.write("This is a file1 ||");
bw.newLine(); //换行API
//写字符串的一部分
bw.write("111我爱你中国",3,3);
//写字符数组
char[] charArray = "||ssssaee方的放的".toCharArray();
bw.write(charArray);
//bw.flush();
//bw.close(); 利用了try方法,不需要这些了
}catch(Exception e){
e.printStackTrace();
}
}
5、出师表案例
需求:将打乱数据的出师表段落按照,每段前面的标号进行排序。
代码演示:
java
public class Test4 {
public static void main(String[] args) throws FileNotFoundException {
//目标:完成出师表案例
//1、准备一个集合,存储原文每段落
List<String> data = new ArrayList<>();
//2、创建缓冲字符输入流与源文件接通
try (
BufferedReader br = new BufferedReader(new FileReader("day10-io-code\\src\\csb.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("day10-io-code\\src\\csb1.txt"));
)
{
String line;
while ((line=br.readLine()) != null){
data.add(line);
}
System.out.println(data);
//4、对每段按照首字符编号进行排序
Collections.sort(data);
System.out.println(data);
//5、新排序的几个中的每段文章写出到新文件中去,每行都要执行
for(String ln : data){
bw.write(ln);
bw.newLine();
}
System.out.println("完成了");
}catch(IOException e){
e.printStackTrace();
}
}
}
6、缓冲流、字节流性能分析
测试用例:
- 分别使用原始的字节流,以及字节缓冲流复制一个很大视频。
测试步骤:
- 使用低级的字节流按照一个一个字节的形式复制文件;
- 使用低级的字节流按照字节数组的形式复制文件;
- 使用高级的缓冲字节流按照一个一个字节的形式复制文件
- 使用高级的缓冲字节流按照字节数组的形式复制文件
代码展示。
注意:低级字节流管道,用数组读写数据,将数组扩大,可以加快传输速度。将数组扩大到8KB,则速度与高级字节流数组传输速度持平。但数组并不是越大越好。
7、不同编码读取乱码的问题
如果代码编码和读取的文本文件的编码是一致的,使用字符流读取文本文件时不会出现乱码。
如果代码编码和被读取的文本文件的编码是不一致的,使用字符流读取文本文件时就会出现乱码。
8、字符输入转换流

InputStreamReader(字符输入转换流)
- 解决不同编码时,字符流读取文本内容乱码的问题;
- 解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。

代码展示:
java
public class InputStreamReaderDemo2 {
public static void main(String[] args) throws FileNotFoundException {
try(
//1、得到GBK文件的原始字节输入流
InputStream is = new FileInputStream("D:\\resource\\abc1.txt");
//2、通过字符输入转换流把原始字节流按照指定编码转换成字符输入流
InputStreamReader isr = new InputStreamReader(is,"GBK");
//3、把字符输入流包装成高级的缓冲字符输入流
BufferedReader br = new BufferedReader(isr);
){
//4、按照行读取
String data;
while ((data = br.readLine()) != null) {
System.out.println(data);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
9、字符输出转换流
需要控制写出去的字符使用什么字符集编码,该咋整?
- 调用String提供的getBytes方法解决?

- 使用"字符输出转换流"实现。
OutputStreamWriter字符输出转换流
作用:可以控制写出去的字符使用什么字符集编码。
解决思路:获取字节输出流,再按照制定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了。

代码演示:
java
public class OutputStreamWriterDemo3 {
public static void main(String[] args) {
try(
//1、目标:掌握字符输出转换值,可以实现写出去的字符编码
//1、创建一个文件字节输出流通向目标文件
OutputStream os = new FileOutputStream("day10-io-code\\src\\dilei06.txt");
//指定写出去的编码是GBK
OutputStreamWriter osw = new OutputStreamWriter(os, "GBK");
//2、把字符输出流包装成缓冲输出流
BufferedWriter bw = new BufferedWriter(osw)
){
bw.write("锄禾日当午");
bw.newLine();
bw.write("汗滴禾下土");
}catch(Exception e){
e.printStackTrace();
}
}
}
10、打印流

PrintStream/PrintWrite(打印流)
作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。
PrintStream提供的打印数据的方案


PrintWriter提供的打印数据的方案


代码展示:
java
public class PrintStreamDemo1 {
public static void main(String[] args) {
//目标:打印流,方便,高效
try(
//PrintStream ps = new PrintStream("day10-io-code/src/ps.txt");
PrintWriter ps = new PrintWriter(new FileWriter("day10-io-code/src/ps1.txt",true));
){
ps.println("Hello World");
ps.println(666);
ps.println('d');
ps.println(true);
}catch(Exception e){
e.printStackTrace();
}
}
}
PrintStream和PrintWriter的区别

打印流的一种应用:输出语句的重定向。
代码展示:
java
public class PrintStreamDemo2 {
public static void main(String[] args) throws FileNotFoundException {
//目标:输出语句的重定向
System.out.println("红豆生南国");
System.out.println("生来发机制");
System.out.println("一二三四五");
PrintStream ps = new PrintStream(new FileOutputStream("day10-io-code/src/ps3.txt"),true);
System.setOut(ps); //把系统类的打印改为我的打印流
System.out.println("楚河而当五");
System.out.println("汗滴禾下土");
}
}
11、特殊数据流

DataOutputStream(数据输出流)
- 允许把数据和其类型一并写出去。


DataInputStream(数据输入流)
- 用于读取数据输出流写出去的数据


传出数据:
代码演示:
java
public class DataOutputStreamDemo1 {
public static void main(String[] args) {
try(
//目标:掌握数据输出流与数据出去的特点,可以写数据和其类型后面可以获取出来
DataOutputStream dos = new DataOutputStream(new FileOutputStream("day10-io-code/src/data.txt"));
){
dos.writeByte(97);
dos.writeBoolean(true);
dos.writeInt(1999);
dos.writeChar('a');
dos.writeUTF("ssqw伟大伟大");
}catch(Exception e){
e.printStackTrace();
}
}
}
写入数据:
代码演示:
java
public class DataInputStreamDemo2 {
public static void main(String[] args) {
try(
DataInputStream dis = new DataInputStream(new FileInputStream("day10-io-code\\src\\data.txt"));
){
//2、开始读取
byte b = dis.readByte();
System.out.println(b);
boolean b1 = dis.readBoolean();
System.out.println(b1);
int i = dis.readInt();
System.out.println(i);
char c = dis.readChar();
System.out.println(c);
String s = dis.readUTF();
System.out.println(s);
}catch(Exception e){
e.printStackTrace();
}
}
}
12、序列化和反序列化
对象序列化:把Java对象写入到文件中去;
对象反序列化:把文件里的Java对象读出来

ObjectOutputStream(对象字节输出流)
- 可以把Java对象进行序列化:把Java对象存入到文件中去。

