字符流
1、概述
字节流对文件进行读写时,如果文件全是英文(英文正好是一个字节),那没什么问题,但是当文件中有中文的时候就会出现乱码(中文在UTF-8里占3个字节)
2、字符流
字符流只能操作有文字的文件(纯文本文件),不能操作非纯文本文件(图片、视频....)
方便程序员查看读取结果,也方便把字符写出到文件目标
使用场景:
操作数据的过程中需要人为的查看数据,数据需要转变为文字(字符),字节流有可能会出现乱码,这种情况下使用字符流
3、字符流的操作原理
字符输入流:
先把字节从文件中读取出来(使用字节流读的),根据文件的编码集把字节数变为对应的字符,把字符读取到内存中
字符输出流:
先把输出的内容一字符形式写出,把字符根据流中的编码集变成字节数,在把字节写到目标文件
以后如果我们只是想单出的完成数据搬运的时候,直接使用字节流即可,因为效率高
如果咱们在搬运数据的时候,需要人为查看,就是字符流
分类:
字符输入流
字符输出流
Reader字符输入流
1、概述
在读取文本文件时数据操作使用单温是字符上的输入流就是字符输入流
他是字符输入流的顶层父类。
2、共性功能
int read():一次读取一个字符 返回值是读到的的字符
int read(char[] ch):一次读取多个字符,存储到char数组中,返回值是读到的有效的字符个数
close():关闭流
3、FileReader
概述:
是Reader的子类(孙子),负责内存和磁盘之间字符的读取交互的流,它没有自己的功能,他的功能就是Reader的功能
构造方法
FileReader(File file):创建一个以file对象对应的文件为目标文件的字符输入流对象
FileReader(String path):创建一个以path路径对应的文件为目标文件的字符输入流对象
代码:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Demo02 {
public static void main(String[] args) throws IOException {
File f = new File("Day21/b/1.txt");
FileReader fr = new FileReader(f);
int len = 0;
char[] c = new char[3];
String s1 = "";
while((len = fr.read(c)) != -1){
String s = new String(c,0,len);
s1 += s;
}
System.out.println(s1);
fr.close();
}
}
Write字符输出流
1、概述
它是字符输出流的顶层父类,它是抽象类,定义了字符输出流的共性方法,不能创建对象,只有实例化子类调用方法功能,子类根据不同设备有不同的子类
2、常用方法
write(int a):写出单个字符到磁盘文件
write(String str):写出字符串到磁盘文件
write(char[] arr):写出字符数组的全部字符到磁盘文件
write(char[] arr,int offset,int len):写出字符数组的部分字符到磁盘文件
offset:写出的开始字符的索引值
len:写出的字符的长度【个数】
不能大于数组的长度
close():关闭流资源
flush():刷新缓冲区
3、FileWrite
概述:
它是Write的间接子类,负责完成内存和磁盘之间字符数据输出交互的流,它没有自己的功能,全是继承自Write的功能
构造方法:
FileWrite(File file):创建以File对象对应的文件为目标文件的字符输出流对象
FileWrite(String path):创建以path路径对应的文件为目标文件的字符输出流对象
注意事项:
①字符输出流创建对象的时候检查目标文件在磁盘中是否存在:
存在:不会自动创建空白文件,但是会对文件进行格式化
不存在:系统自动创建一个空白文件出来
public class Demo01 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("Day21/b/2.txt");
fw.write('我');
fw.write("略略略略");
char[] cs = {'中','公','教','育'};
fw.write(cs);
fw.close();
}
}
字符流的文件拷贝
1、概述
文件的拷贝如果只是单纯的转移数据,文件数据在磁盘存储时都是由字节组成,不需要使用字符流来进行拷 贝.只有在拷贝的过程中需要对里面数据进行查看或操作的时候可以使用字符流进行拷贝,否则在使用字符流 进行文件拷贝做了一对没有意义互斥操作,(读取的时候会做一次解码操作,写出的时候会做一次编码的操作). 但是只有纯文本文件才可以使用字符流进行拷贝。
package com.offcn.demo03;
import jdk.jfr.events.FileReadEvent;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo01 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("Day21/b/3.txt");
FileWriter fw = new FileWriter("Day21/b/copy1.txt");
int i = 0;
while((i = fr.read()) != -1){
fw.write(i);
System.out.println((char)i);
}
fw.close();
fr.close();
}
}
字符缓冲流(高效字符输入输出流)
1、概述
就是用来给字符流提升效率的一个流,他可以理解为就是一个普通字符流进行包装的工具流。本身没有操作数据的功能,但是结构衍生了可以操作流的功能,属于他特有的功能
2、分类
字符输入缓冲流【BufferedReader】增强普通字符输入流
字符输出缓冲流【BufferedWrite】增强普通字符输出流
3、构造方法
BufferedReader(Readerr r):创建一个提升指定字符输入流r的效率的字符输入缓冲流对象
BufferedWriter(Writer w):创建一个提升指定字符输出流w的效率的字符输出缓冲流对象
package com.offcn.demo03;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class Demo03 {
public static void main(String[] args) throws Exception{
FileReader fr = new FileReader("Day21/b/3.txt");
FileWriter fw = new FileWriter("Day21/b/copy3.txt");
BufferedReader br = new BufferedReader(fr);
BufferedWriter bw = new BufferedWriter(fw);
int i = 0;
while((i = br.read()) != -1){
bw.write(i);
}
bw.close();
fw.close();
br.close();
fr.close();
}
}
4、特有方法
字符输入缓冲流【BufferedReader】:
String readerLine():一次读取一行的数据【行不是屏幕上的看到的行】读取文件末尾的标志,返回null
字符输出缓冲流【BufferedWriter】:
new Line():换行
package com.offcn.demo03;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class Demo04 {
public static void main(String[] args) throws Exception{
BufferedWriter bw = new BufferedWriter(new FileWriter("Day21/b/5.txt"));
bw.write("日照香炉生紫烟");
bw.newLine();
bw.write("遥看瀑布挂前川");
bw.newLine();
bw.close();
}
public static void text1()throws Exception{
BufferedReader br = new BufferedReader(new FileReader("Day21/b/4.txt"));
String s = "";
while ((s = br.readLine()) != null){
System.out.println(s);
}
br.close();
}
}
转换流
1、java程序使用的是ASICII码表,但是从外部进来的文件不一定是这个表,你要写的文件也不一定是用ASICII码表,所以就有了转换流
2、转换流
它是字符流子类,转换流本质是字符流,只能操作纯文本文件,它可以对字符流的编码集进行指定转换。
作用:
①指定IO流的操作的使用编码集
②完成字节流和字符流的相互转换
分类:
输入转换流【InputStreamReader 字符流】字节流通向字符流的桥梁
创建的时候使用它提供的构造方法:
InputStreamReader(InputStream is,String charsetName),传入一个字节输入流,把字节输入流读取到的字节信息使用指定字符集名称转为字符,就可以避免读取操作的乱码。
输出转换流【OutputStreamWriter字符流】字符流转为字节流的桥梁
创建的时候使用它提供的构造方法:
OutputStreamWriter(OutputStream os,String charsetName),传入字节输出流,把要写的字符信息,使用指定字符集转为字节数据,再使用字节流把字节数据写到目标文件,避免写出数据是乱码的出现
(一)InputStreamReader【输入转换流】
1、概述
它是字符输入流Reader的子类,是字节流到字符流的桥梁,本质是字符流,只能操作纯文本文件
理解:是对字节输入流的包装,包装后字节流变为字符流转换
2、构造方法
InputStreamReader(InputStream is,String charSetName):创建一个指定编码集的输入转换流对象
参数1:字节输入流对象,InputStream字节流顶层父类
参数2:字符集名称
工作原理:
使用字节输入流字节信息读取到内存中,再参考指定的字符集把字节信息转为字符,转换流读取到就是字符信息了。
package com.offcn.demo04;
import java.io.FileInputStream;
import java.io.InputStreamReader;
public class Demo01 {
public static void main(String[] args) throws Exception{
InputStreamReader isr = new InputStreamReader(new FileInputStream("Day21/b/1.txt"),"GBK");
int i = 0;
while ((i = isr.read()) != -1){
System.out.println((char)i);
}
isr.close();
}
}
(二)OutputStreamWriter【输出转换流】
1、概述
属于字符输出流的子类,本质是字符流,所以它的功能就是Writer类的功能,它是字符流到字节流的桥梁
理解为:对字节输流的一种包装,包装后变为字节输出流
2、构造方法
OutputStreamWriter(OutputStream os,String charSet):
参数1:字节输出流对象,OutputStream字节输出流的顶层父类
参数2:字符集名称
创建一个指定编码集以及转换后的字节输出流的转换流对象
功能及时字符输出流的功能,同样可以被字符输出缓冲流提效
OutputStreamWriter写出字符的时候,会使用指定的字符集把字符转为字节信息,再用传入的字节流输出到目标文件
package com.offcn.demo04;
import java.io.*;
public class Demo02 {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("Day21/d/1.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
osw.write("我爱java");
osw.close();
}
}
总结:
1.如果操作IO操作文件字符集和java程序字符集一致的时候,就没有必要使用这两个流.
2.当IO操作字符集和Java程序不一致时,就要使用InputStreamReader读取文件,只要保证读取时指定字符集和目标文件字符集一致即可. 写出时候就要使用OutputStreamWriter,,只要保证写出时指定字符集和目标文件字符集一致即可.
无论是转换输入流,还是转换输出流, 指定字符集的时候,都是参考要操作的文件字符集来设置, 文件是什么字符集,就指定什么字符集.
标准输入输出流
标准输入流
System.in:该流的类型为InputStream,属于是字节流,默认关联的设备是键盘,即数据源为键盘
如何提供标准输入的输入能力:
使用转换流InputStreamReader可以包装称字符流,使用BufferedReader可以包装成缓冲流
通过System.setIn(InputStream in),可以更改标准输入流关联的设备
该流对象不需要关闭
修改关联设备注意事项:
①先修改关联设备
②再获取标准输入流
package com.offcn.demo05;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Demo01 {
public static void main(String[] args) throws IOException {
InputStream in = System.in;
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
System.out.println(s);
}
public static void test() throws Exception{
InputStream in = System.in;
int i = in.read();
System.out.println(i);
byte[] bs = new byte[10];
int len = in.read(bs);
System.out.println(new String(bs,0,len));
}
}
标准输出流
System.out:该流的类型为PrintStream,属于字节流,是字节打印流。是OutputStream的孙子辈类
默认关联的设置是控制台,即可以将数据直接写到控制台显示
通过System.setOut(PrintWriter out),可以更改标准输出流关联的设备
修改关联设备注意事项:
1.先修改关联设备
2.再获取标准输出流
package com.offcn.demo05;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class Demo02 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("Day21/d/2.txt");
System.setIn(fis);
InputStream in = System.in;
int i = 0;
while ((i = in.read()) != -1){
System.out.println((char)i);
}
}
}