IO就是存储和读取数据的解决方案
IO的分类
IO流体系
字节流
FileOutStream
import java.io.*;
public class iotset {
public static void main(String[] args) throws IOException {
//创建对象(细节:①默认覆盖写,参数true打开续写 ②可以使路径也可以是File对象 ③不存在文件会自动创建)
FileOutputStream fileOutputStream = new FileOutputStream("F:\\JavaBase\\src\\io\\myio.txt",true);
byte a[] = {90,89,88,87};
//三种参数类型,写数据(细节:ASCII值)
fileOutputStream.write(90);
fileOutputStream.write(a);
fileOutputStream.write(a,2,2);
//换行
fileOutputStream.write("\n".getBytes());
//写出字符串
fileOutputStream.write("woyaoxuexi".getBytes());
//关闭资源(细节:每次用完需要释放资源,不然会一直占用文件)
fileOutputStream.close();
}
}
FileInputStream
//创建输入流对象(细节:①文件不存在报错,不会自动创建)
FileInputStream fileInputStream = new FileInputStream(new File("F:\\JavaBase\\src\\io\\myio.txt"));
//进行读取(细节:①读出来是ASCII数值 ②读到最后返回-1)
int read;
while ((read = fileInputStream.read()) != -1){
System.out.println((char)read);
}
//批量读取
byte[] a= new byte[10];
int read1;
while ((read1 = fileInputStream.read(a)) != -1){
String s =new String(a,0,read1);
System.out.println("s = " + s);
}
//关闭资源
fileInputStream.close();
文件拷贝:就是一边读一边写到复制文件中
try catch 的优化:在小括号中创建对象,会自动释放资源。只有实现了AutoCloseable的接口才能写到小括号中。
字符集
ASCII(不支持汉字)
GBK(一个英文一个字节,0开头。一个中文两个字节,1开头)
Unicode(一个英文一个字节,0开头。一个中文三个字节,1110开头 10开头 10开头)
出现乱码的原因:
①字节流读取一个字节一个字节读取,截断了汉字的三个字节。
②编码和解码使用的规则不同。
字符流
FileReader
import java.io.*;
public class iotset02 {
public static void main(String[] args) throws IOException {
//创建对象
FileReader fileReader = new FileReader(new File("F:\\JavaBase\\src\\io\\myio.txt"));
//读取数据(细节:①底层是字节流,一次读一个字节,遇到中文就读三个字节 ②底层中文会被解码为十进制,再返回)
int ch;
while ((ch = fileReader.read()) != -1){
System.out.print((char)ch);
}
//读取多个(细节:读取+解码+强转为char)
char[] a =new char[2];
int len;
while ((len = fileReader.read(a)) != -1){
System.out.print(new String(a,0,len));
}
//关闭资源
fileReader.close();
}
}
FileWriter
//创建对象
FileWriter fileWriter = new FileWriter(new File("F:\\JavaBase\\src\\io\\myio.txt"));
//写数据(细节:①默认为覆盖写,true可设置)
fileWriter.write(20390);//写一个字符
fileWriter.write("学习");//写一个字符串
fileWriter.write("学习?学个屁",3,3);//写一个字符串的一部分
char[] a = {'b','c','d','e'};
fileWriter.write(a);//写一个字符数组
fileWriter.write(a,3,2);//写一个字符数组的一部分
//关闭资源
fileWriter.close();
字符输入流底层原理详解 (创建一个长度为8192缓冲区,第一次读的时候缓冲区无数据,然后就会把数据尽量装满缓冲区,之后就先看缓冲区有没有数据,如果没有就会去文件读)
字符输出流底层原理详解(也是在内存中创建一个缓冲区,写数据时先把数据放到缓冲区中,然后从缓冲区写到磁盘中的条件有:①写入缓冲区的数据超过了8192大小,缓冲区的数据就会全部写入磁盘。②使用flush()会把缓冲区数据刷到磁盘。③close(会检查缓冲区中是否还有数据,然后写进磁盘))
字节流和字符流的使用场景
高级流--缓冲流
字节缓冲流
底层原理:在内存中创建一个长度大小为8192大小的缓冲区,①输入缓冲流则是每次把数据读到缓冲区中,内存在缓冲区中拿到数据,如果缓冲区全部读完了,又会重新去磁盘文件再读到缓冲区。②输出缓冲流则是每次把输出的数据先放到缓冲区中,然后当缓冲区满了,或者flush,或者close就把数据刷到磁盘中去。
字符缓冲流
因为字符流已经有缓冲区提高效率,但是字符缓冲流提供了按行读取和写入
import java.io.*;
public class highIo {
public static void main(String[] args) throws IOException {
//创建对象
BufferedReader bufferedReader = new BufferedReader(new FileReader("F:\\JavaBase\\src\\io\\myio.txt"));
//读取数据
String s;
//读取一行数据
while ((s=bufferedReader.readLine()) != null){
System.out.println("s = " + s);
}
//释放资源
bufferedReader.close();
//创建对象
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("F:\\JavaBase\\src\\io\\myio.txt",true));
//写入数据
bufferedWriter.newLine();//换行
bufferedWriter.write("我能输出一行");
//释放资源
bufferedWriter.close();
}
}
注:字节缓冲流的缓冲区:8192字节即8KB,而字符缓冲流的缓冲区:8192字符即16KB
高级流--转换流
从转换流读,jdk11在FileReader中添加一个构造方法,原先的形式已经淘汰
从转换流写出,jdk11在FileReader中添加一个构造方法
高级流--序列化流
序列化流写对象:
反序列化流读取对象:
细节1:当写入后修改了javabean的属性再读入是就会报错
解决方案:固定版本号,在对象类数添加属性
细节二:当我们不想对象的某个属性写到文件中,可以在属性名前加transient
细节三:可以使用List包装多个对象进行读写操作
高级流--打印流
只有输出流才有打印流
字节打印流
字符打印流
扩展:System.out.println实际上就是字符打印流
高级流--压缩流
解压
压缩