IO流的分类:
按照数据流向分类:
输入流:读入数据
输出流:写出数据
按照数据类型分类:
字节流
字符流
什么情况下使用哪种流呢?
如果数据所在的文件通过windows自带的记事本打开并能读懂里面的内容,就用字符流。其他用字节流。
字节流的抽象基类:
InputStream ,OutputStream。
字符流的抽象基类:
Reader , Writer。
由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
如:InputStream的子类FileInputStream。
如:Reader的子类FileReader。
字符缓冲流:
BufferedWriter:字符缓冲输出流
BufferedReader:字符缓冲输入流
String类中的编码和解码
public String(byte[] bytes, Charset charset):通过使用指定的字符集解码字节数组。
public byte[] getBytes(Charset charset):使用指定的字符集把字符串编码为字节数组。
编码:把看得懂的变成看不懂的
解码:把看不懂的变成看的懂的。
把字符串编码为字节数组:默认是gbk
String s = "你在吗?";
byte[] bys = s.getBytes(); //默认是gbk
byte[] bysGBK = s.getBytes("gbk");
byte[] bysUTF = s.getBytes("UTF-8");
System.out.println(Arrays.toString(bys)); //[-60, -29, -44, -38, -62, -16, -93, -65]
System.out.println(Arrays.toString(bysGBK)); //[-60, -29, -44, -38, -62, -16, -93, -65]
System.out.println(Arrays.toString(bysUTF)); //[-28, -67, -96, -27, -100, -88, -27, -112, -105, -17, -68, -97]
把字节数组解码为字符串:默认也是gbk
String s = "你在吗?";
byte[] bys = s.getBytes(); //通过默认编码(gbk)编码转换为字节数组
String ss = new String(bys); //通过默认编码(gbk)解码转换为字符串
String ssGBK = new String(bys,"gbk");
System.out.println(ss); //你在吗?
System.out.println(ssGBK); //你在吗?
解码和编码的格式必须一致才能正确:
String s = "你在吗?";
byte[] bys = s.getBytes("UTF-8"); //采用UTF-8字符集来编码
String ssUTF = new String(bys,"UTF-8"); //通过UTF-8字符集来解码
String ssGBK = new String(bys,"gbk"); //通过gbk字符集来解码(跟编码的字符集不相同,因此会报错)
System.out.println(ssUTF); //你在吗?
System.out.println(ssGBK); //浣犲湪鍚楋紵
OutputStreamWriter 字符输出流
public OutputStreamWriter(OutputStream out):根据默认编码把字节流的数据转换为字符流(gbk)
public OutputStreamWriter(OutputStream out, String charsetName):根据指定编码把字节流数据转换为字符流
字节流 = 字符流 + 编码表
OutputStreamWriter = FileOutputStream + 编码表(默认gbk)
编码格式问题
//创建对象(默认gbk)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"));
OutputStreamWriter oswGBK = new OutputStreamWriter(new FileOutputStream("oswGBK.txt"), "gbk");
//向文件中写数据
osw.write("我是用默认编码写的:想你");
oswGBK.write("我是用gbk写的:想你");
osw.close();
oswGBK.close();
OutputStreamWriter的方法:
public void write(int c):写一个字符
public void write(char[] cbuf):写一个字符数组
public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
public void write(String str):写一个字符串
public void write(String str,int off,int len):写一个字符串的一部分
//创建对象(默认gbk)(向文件中写数据,相对于程序来说,就是向外输出,向外去写,所以是OutputStreanWriter)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"));
osw.write('a'); //写一个字符
osw.write(); //写一个字符
osw.write('\n'); //写一个字符
char[] chs = {'i','l','o','v','e','y','o','u'};
osw.write(chs); //写一个字符数组
osw.write('\n'); //写一个字符
osw.write(chs, , ); //写一个字符数组的一部分
osw.write('\n'); //写一个字符
osw.write("你最漂亮",, ); //写一个字符串的一部分
osw.close(); //close方法会先刷新,然后在关闭。
close()和flush()的区别是什么?
1、close():关闭流对象前,要先刷新缓冲区。在关闭该流之后,流对象不可以继续再使用,再调用 write() 或 flush() 将导致抛出 IOException。
2、flush():仅仅刷新缓冲区,刷新之后流对象还可以继续使用。
数据之前保存在缓冲区,当flush刷新之后数据才会写入文件中。
InputStreamReader 字符输入流
public InputStreamReader(InputStream in):用默认的编码读取数据(gbk)
public InputStreamReader(InputStream in,String charsetName):用指定的编码读取数据
字节流 = 字符流 + 编码表
InputStreamReader = FileInputStream + 编码表(默认gbk)
编码格式问题:解码使用的字符集格式必须和编码使用的字符集格式相同此案呢个者却的解码
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"));
//从文件中一次读取一个字符(char)(采用默认编码格式读取)
int ch = ;
while((ch = isr.read()) != -){
System.out.print((char)ch);
}
System.out.println();
System.out.println("-------");
//采用gbk编码读取文件中字符
InputStreamReader isrGBK = new InputStreamReader(new FileInputStream("osw.txt"),"gbk");
int chGBK = ;
while((chGBK = isrGBK.read()) != -){
System.out.print((char)chGBK);
}
InputStreamReader的方法:
int read():一次读取一个字符
int read(char[] chs):一次读取一个字符数组
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"));
//一次读取一个字符:read()(效率很低)
int ch = ;
while((ch = isr.read()) != -){
System.out.print((char)ch);
}
//一次读取一个字符数组
char[] chs = new char[];
int len = ;
while((len = isr.read(chs)) != -){
System.out.print(new String(chs,,len));
}
实现文件的复制:
//数据源
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
//目的地
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));
//读写数据
char[] chs = new char];
int len =;
while((len = isr.read(chs)) !=){
osw.write(chs,len); //写字符数组的指定部分
osw.flush(); //当资源多的时候,需要flush,少可以不用
}
osw.close();
isr.close();
转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类。FileWriter和FileReader作为子类来代替InputStreamReader和OutputStreamWriter
FileWriter 和 FileReader( 作为OutputStreamWriter 和 InputStreamReader的子类)
public class FileWriter extends OutputStreamWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream上构造一个 OutputStreamWriter。
复制文本文件
//封装数据源
FileReader fr = new FileReader("a.txt");
//封装目的地
FileWriter fw = new FileWriter("c.txt");
//一次一个字符
int ch =;
while((ch = fr.read()) !=){
fw.write(ch);
}
// 一次一个字符数组
char[] chs = new char];
int len =;
while((len = fr.read(chs)) !=){
fw.write(chs,, len);
fw.flush();
}
fw.close();
fr.close();