一、缓冲流
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
按照数据类型分类:
字节缓冲流: BufferedInputStream , BufferedOutputStream
字符缓冲流: BufferedReader , BufferedWriter
1.1 字节缓冲流
读取方法与基本的流一致
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\111\\aaa"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\111\\bbb"));
int len;
byte[] b = new byte[1024];
while ((len = bis.read()) != -1){
bos.write(len);
}//每次读写一个字节,速度慢
while((len = bis.read(b)) != -1){
bos.write(b,0,len);
}//每次读写数组长度个字节
bos.flush();//记得刷新,否则文件内容没有被复制到新文件
bos.close();
bis.close();
}
1.2 字符缓冲流
使用方法同上
特有方法:
BufferedReader: public String readLine() : 读一行文字。
BufferedWriter: public void newLine() : 写一行行分隔符,由系统属性定义符号。
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("E:\\111\\aaa"));
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\111\\bbb"));
String line;
/*while((line = br.readLine()) != null){
System.out.println(line);
}*/
//读取一行写到bw的文件中
while((line = br.readLine()) != null){
bw.write(line,0,line.length());
bw.newLine();//转行
}
bw.flush();
bw.close();
br.close();
}
二、转换流
按照A规则存储,同样按照A规则解析,那么就能显示正确的文本符号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。
字符编码 : 就是一套自然语言的字符与二进制数之间的对应规则。
字符集 : 也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。
2.1 InputStreamReader类
是从字节流到字符流的桥梁。它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。
public static void main(String[] args) throws IOException {
InputStreamReader isr1 = new InputStreamReader(new FileInputStream("E:\\111\\bbb.txt"));//默认编码,idea中默认UTF-8编码
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("E:\\111\\bbb.txt"),"GBK");//指定编码表
int len;
while((len = isr1.read()) != -1){
System.out.println((char) len);
}
}
2.2 OutputStreamReader类
是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集将字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。
使用方法同上
三、序列化
3.1 ObjectOutputStream类
将Java对象的原始数据类型写出到文件,实现对象的持久存储。
序列化操作:
一个对象要想序列化,必须满足两个条件:
1.该类必须实现 java.io.Serializable 接口
2.该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用transient 关键字修饰。
public class Student implements Serializable {
private String name;
private int age;
private transient String hobby; //transient修饰,不被序列化
//省略了构造方法和get、set方法
}
public class Test4 {
public static void main(String[] args) throws IOException {
Student stu = new Student("哈哈哈",19,"学习");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("E:\\111\\ccc"));
out.writeObject(stu);
out.close();
}
}
3.2 ObjectInputStream类
将之前使用ObjectOutputStream序列化的原始数据恢复为对象。
//接上个代码
public class Test5 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\111\\ccc"));
Student stu = (Student) ois.readObject();
System.out.println(stu.getName() +" "+ stu.getAge());
}
}
输出结果:
哈哈哈 19
四、打印流
PrintStream类
构造:public PrintStream(String fileName) : 使用指定的文件名创建一个新的打印流。
System.out 就是 PrintStream 类型的,只不过它的流向是系统规定的,打印在控制台上。不过,我们可以改变它的流向。
public class Test6 {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("E:\\111\\aaa");
System.setOut(ps);//设置系统的打印流流向,输出到aaa文件中
ps.println("fjkjhb9");//打开aaa文件可看到输出的内容
}
}