概述
I(input):输入
O(output): 输出
IO流分为字符流和字节流
字符流是只能操作纯文本的文件,以字符(2个字节)为单位进行数据读写的流
字节流可以操作任意类型的文件,以字节为单位进行数据读写的流
| | 字符流 | 字节流
|输入流| 字符输入流(reader)|| 字节输入流(InputStream) 超类
|输出流| 字符输出流(writer) || 字节输出流 (OutputStream)
进到程序中的内容叫输入
从程序发出的内容叫输出,
输入流:从文件中读取内容输入到程序中,也就是读文件
输出流:将程序中的数据内容输出到文件中。也就是写文件
以程序为中心
上面的顶级父类都是抽象类,不能直接使用
ctrl+alt+f : 快捷键格式化代码
字符输入输出流
抽象基类 : Reader、Writer
是字符输入输出流的超类
以字符为单位读写数据,一次处理一个unicode
字符流的底层是字节流
访问文件:FileReader、FileWriter
FileWriter
字符输出流,基本的流。从内存中写入到文件中
主要用于将文本内容写入到文本文件
//创建一个新文件,如果没有,直接创建。如果有,替换为这个。只能创建一个文件,不能创建文件夹
FileWriter fileWriter = new FileWriter("D:\\a.txt");
String str = "abcdefg";
//fileWriter.write((可以写数字或者单个的字符,数字会转换成对应的阿斯克码))
//在指定字符数组中从下标1开始的3个字符写入此文件的输出流
fileWriter.write(str,1,3);
//冲刷缓冲区:fileWriter.flush()
//内存中的数据并不是直接到文件中,而是先到缓冲区,等待积累部分后再到文件中
//如果不冲刷,则会和内存一起消失,不会到文件中
//关闭流,关闭流时会自动重刷一次缓冲区
fileWriter.close();
//将这个流对象标记为垃圾对象
fileWriter = null;
FileReader
字符输入流,返回int值
主要用于从文本文件读取文本数据内容
public static void main(String[] args) throws IOException {
//创建流对象,指向要读取的文件
FileReader reader = new FileReader("D:\\abc.txt");
//创建字符数组作为缓冲区
char[] cs = new char[5];
int len;
//read是读取单个字符的数量并返回,返回-1表示读取到末尾
while((len = reader.read(cs)) != -1){
System.out.println(len);
System.out.println(new String(cs,0,len));
}
reader.close();
}
}
字符打印输出流PrintWriter,字符打印输入流PrintReader
有独特的方法可以实现换行的操作
PrintWriter
向文件中写入可以换行的字符串
高级流 :PrintWriter 可以直接连接程序和文件 是因为 其内部包含fileoutputStream,outputstreamwriter,bufferedwriter
PrintWriter pw = new PrintWriter(“要写入的文件名”);
pw.println(“写入的内容”,true);//true 表示自动行刷新,输完一行就输出一行
只能输出
缓冲字符输出输入流:BufferedWriter,BufferedReader。高级流:在其他流上添加就可以加入额外的功能
每次读8192个字符
BufferedWriter
用于写入单个字符,字符数组及字符串到输出流中。
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("一个路径"))
BufferedReader
作用:
1.块读文本数据,加速传输
2.用于从输入流中读取单个字符,字符数组以及字符串
BufferedReader bufferedreader = new BufferedReader(new FileReader("一个路径"))
bufferedreader.readline()可以读取一行,返回一个字符串,当返回null时说明已经读完
转换流 InputStreamReader,OutputStreamReader
所有的字符流,除了转换流。不能直接连接在字节流fis,fos上。所以转换流可以让更高级的字符流和字节流连接
InputStreamReader《FileInPutStream》
可以输出文件中的字符
字符输入流
主要实现从字节流到字符流的转换
FileInputStream fis = new FileInputStream("要读取的文件名")
InputStreamReader isr = new InputStreamReader(new FileInputStream(fis,StandardCharsets.UTF_8);
int d = isr.read(); //与字节流不同,字节流每次读取一个字节,字符流read()每次读取一个字符
就是char类型的,只不过用int接收。一个char是两字节,16位二进制 。返回-1说明读取到了末尾。用-1是因为最大是 00000000 00000000 11111111 11111111 不可能是-1
OutputStreamWriter 需要连接《FileOutPutStream》
字符输出流
实现字符流到字节流的转换,因为字符可以更加方便的操作,因为字符不能直接写入到文件中
可以用write方法直接输入字符串到文件中
FileOutputStream fos = new FileOutputStream("输出到哪一个文件夹")
OutputStreamWriter osw = new OutputStreamWriter(fos,StandardCharsets指定字符集)
osw.write("要写的字符串") //写入文件中
osw.close();
字节输入输出流
inputstream、outputstream是字节输入输出的超类
(重点)访问文件 FileInPutStream,FileOutPutStream
FileInPutStream
低级流
真实连接文件的流,用来读取文件的数据
在程序中以字节流的方式读取图像数据等
有块读取操作,一次读取一个byte[]数组,数组自己规定读缩少字节。注意 读的字节不足时,前面只是覆盖,后边还是原字节
FileIutputStream fis = new FilwIutputStream("加入文件路径名"或File file文件);/
int d = fis.read();//每次读取一个字节,也就是8位二进制,每次调用read()后自动移动8位以便读取后边的值,返回到int型是32位所以前24位自动补零
int d = fis.read();//多次读取后没有值了返回-1
int d;
while((d = fis.read())!=-1){fos.write(d);}//复制文件.每次传输8位,直到传输完成返回-1
//使用块读
byte[] data = new byte[1024*10];//默认初始为0
int d;//记录每次读写的数据量,如果读完了则返回-1
while((d=fis.read(data)) != -1){ // 返回读取的字节个数给d
fos.write(data);
}
或者 while((d=fis,read(data)) != -1){fos.write(data,0,d)}//给它设定范围,仅复制从下标0开始d个(d代表长度)有效数值,不会在最后一次也赋值全部的byte数据
使用块读字符串
//1.读取文件中的所有的字节
File file = new File("fos.txt");
long len = file.length();
FileInputStream fis = new FileInputStream(File);
byte[] data = new byte[(int)len];
fis.read(data);//将所有字节读入到data数组中
//2.将这些字节转换为字符串
String line = new String(data,StandardCharsets.UTF-8);
sout(line);
fis.close();
FileOutPutStream
将图像数据之类的原始字节流写入到文件中
gbk:国标编码
Unicode:国际每个字符都有独特的编码,通过2个字节包含,65536个组合包含世界上的常用字符,但日常传输不使用,因为没有分隔符计算机不知道如何分1010看
UTF-8 :有分隔符的Unicode,每个中文字变成了三个字节
//创建了一个流
FileOutputStream fos = new FilwOutputStream("加入文件路径名"或File file文件);//文件名不存在会自动创建
fos.write(2)//2是int型,有32位,但是write只会写低8位,一个字节。输出时将低八位对应的阿斯克码值显示出来。这个方法是写入字节数据的。括号内不能写Stirng类型的,的,可以使用.getbytes()将字符串转为字节数组
//字节遵循阿斯克码,例如输入97就代表a
1,2,4,8,16,32,64,128,
fos.close();//最终操作后关闭
// 1111 1111 代表-1 第一个是符号位,后边的1代表是负数里最大的。第一位是符号位代表补码
// 1000 0000 代表-127 ,后边的0代表是负数里最小的
//使用块写字符串
String line = "怎么办呢";
byte[] data = line.getBytes(StandardCharsets.UTF-8);
//覆盖模式 :默认不写则为false,覆盖模式若原文件存在重新运行时原来的数据不保留,直接先清空再执行新的
//追加模式:FileOutputStream fos = new FilwOutputStream("加入文件路径名"或File file文件,ture);,加入true说明是追加模式,追加模式下在文件运行时不会清空文件内容而是会保留
fos.write(data);
sout("写入完毕");
fos.close();
(重点)缓冲流 BufferInputStream,BufferOutPutStream。高级流,在低级流之上,给低级流添加功能
功能:在流链接中加块读写效率。底层是一次传8*1024个字节,它读取不了字符
缓冲流是最接近低级流的高级流
FileInputStream fis = new FileInputStream("路径");
BufferedInputStream bis = new BufferedInputStream(fis)
bis.read()
bos.write()
BufferInputStream 输入流
描述缓冲输入流
FileOutputStream fos = new FileOutputStream("路径");
BufferedOutputStream bos = new BufferedOutputStream(fis)
BufferOutputStream 输出流
主要用于描述缓冲输出流,并不是每次调用 write() 都会立即写入到磁盘,而是先缓冲到内存中。当缓冲区满了或者调用 flush() 方法时,才会将数据真正写入到文件中,这样可以减少与磁盘的交互次数,提高写入效率。
但这样会有写缓冲问题,因为如果bos的数组没有装满,是不会送到cpu,所以在close()的时候,数据也丢失了,并没有送到地方
bos.flush();//强制将缓冲流的全部字节一次性写出
所有字节输出流都有flush方法,比缓冲流更高级的流调用flush()方法时的目的是,调用更低一级的flush流,直到调用到bos.flush()
(重点)对象流 ObjectInputStream,ObjectOutPutStream
作用
创建对象时如果有不用的,可以用transient 修饰,被修饰的对象不再传输,序列化的字节中没有这个值。如果该对象没有序列化,则transient不发挥任何效果
ObjectInputStream
java.io.ObjectInputStream类主要用于从输入流中一次性将对象整体读取出来。
将对象转化为可以保存的字节
所谓反序列化主要指将有效组织的字节序列恢复为一个对象及相关信息的转化过程。
FileIutputStream fis = new FileIutputStream("路径名 必须是经过序列化的文件")
ObjectIutputStream ois = new ObjectIutputStream(fis)
ois.readObject(); 返回的并不是你创建的对象,而是Object对象
类 类名 = (类名)ois.readObject();//向下造型
sout(类名)
transient 关键字
当一个属性被transient关键字修饰后,在进行序列化时转换出来的字节是不包含该属性的
可以节省传输时间
ObjectOutPutStream
java.io.ObjectOutputStream类主要用于将一个对象的所有内容整体写入到输出流中。
只能将支持 java.io.Serializable 接口的对象写入流中。
类通过实现 java.io.Serializable 接口以启用其序列化功能。
Serializable是签名接口,里面是空的,没有要实现的方法
所谓序列化主要指将一个对象需要存储的相关信息有效组织成字节序列的转化过程。
FileOutputStream fos = new FileOutputStream("路径名")
ObjectOutputStream oos = new ObjectOutputStream(fos)
oos.writeObject(类的名字);//将给定的对象转换为字节,然后通过其连接的流将字节写出.这个类必须实现Serializable接口。否则报错
oos.close();
StringBuilder 不安全但是常用
StirngBuilder builder ;builder.append(“”)
StringBuffer 安全但是不常用,因为没人会在多线程的情况下操作字符串