一、IO流的定义
二、 字节流
(一)FileOutputStream
操作本地文件的字节输出流,可以把程序中的数据写到本地文件中。
1、书写步骤
注:
(1)创建字节输出流对象:
- 参数是字符串表示的路径或者是file对象都是可以的。
- 如果文件不存在,会创建一个新的文件,但要保证父级路径是存在的。
- 例如:("父级路径\\文件名.txt")
- 如果文件已经存在,会清空文件。
(2)写数据
- write方法的参数是整数,但实际上写到本地文件的是整数在ASCII上对应的字符,
- 也就是说:write里面的参数是ASCII码。可以'97'.getByte()
(3)释放资源
- 每次使用完流后要释放资源
- 不释放的话,在本地无法操作,例如你想删了删不掉,显示正在占用
2、写数据的3种方式
3、换行写
Windows:换行符\r\n,但由于java对回车换行进行了优化,所以只写1个 \n或者\r就行
Linux:\n
4、续写
append传递true的话,就开启续写了,false的话关闭续写,再次创建对象会清空文件
(二)FileInputStream
1、创建字节输入流对象
(1)创建字节输入流对象
- 如果文件不存在,会直接报错
- 这一点和输出流不同,输出流最重要的是要输出的数据,所以如果文件不存在,自动创建一个就好。而输入流要读数据,文件不存在时创建一个空文件来读空的数据是没有意义的。
(2)读取数据
- 一次读一个字节,读出来的是ASCII码
- 读到文件末尾了,read方法返回-1
(3)释放资源
- 每次使用完流必须要释放资源
2、读数据.read()
read()会逐个逐个的读取,如果得不到了,返回的是-1,其他正常返回的是ASCII码,如果想输出字符串形式的,就强转(char)
3、循环读取
(三)拷贝
1、每次读取1个字节可以满足——>小文件
2、每次读取多个字节——>大文件
1024的整数倍
由于第3次只剩下1个e了,写入bytes[0] = e,但bytes[1]没有被覆盖,所以第3次读取的是ed。
如果还要继续读取第4次,由于什么也没有读到,会自动返回-1。
为了防止这种现象,可以利用上len:这样就不会在最后出现打印了上次读取的数据的情况
FileInputStream fis = new FileInputStream ("D:\\movie.mp4");
FileOutputStream fos = new FileOutputStream ("myio\\copy.mp4");int len;
byte[] bytes = new byte[1024*1024*5];//这是5M的大小while((len = fis.read(bytes)) != -1){fos.write(bytes,0,len);}
若要记录运行的时间:
//开始时间:
long start = System.currentTimeMillis();//程序//结束时间
long end = System.currentTimeMillis();//用时
end-start
(四) 可能的异常IOException
(五) 字符集
乱码问题
存储英文一个字节足以
1、GBK
一个汉字用两个字节来存储,包含高位字节和低位字节
2、Unicode
中文的第一个字节的首位,一定是1
UTF-8是Unicode字符集的一种编码方式,而不是字符集
3、为什么会有乱码
(1)读取数据时未读完整个汉字
(2)编码和解码的方式不统一
三、字符流
(一)FileReader
有参的read方法 = 空参的read方法 + 强制类型转换
(二)FileWriter
(三)字符输入流的底层原理
(四)字符输出流的底层原理
以下三种方法可以把缓存区中的数据拿出来:
结果:
经过flush或者close的都从缓冲区拿出来了,但close结束后的B站就无法write了。
四、字节流和字符流的使用场景
1、拷贝练习
public class Main {public static void main(String[] args) throws IOException {File src = new File("D:\\AAA\\SRC");File sDEST = new File("D:\\AAA\\DEST");COPYDIR(src,sDEST);}private static void COPYDIR(File src, File sDEST) throws IOException {sDEST.mkdirs();//递归//1、进入数据源File[] files = src.listFiles();//2、遍历数组for (File file : files) {if(file.isFile()){//3、判断文件,拷贝FileInputStream fis = new FileInputStream(file);FileOutputStream fos = new FileOutputStream(new File(sDEST,file.getName()));byte[] buffer = new byte[1024];int length;while((length = fis.read(buffer))!=-1){fos.write(buffer,0,length);}fis.close();fos.close();}else{//4、判断文件夹,递归COPYDIR(file,new File(sDEST,file.getName()));}}}
}
2、文件加密
采用的加密解密方式:异或同一个数,得到原本的数..
解密和加密的代码一样:
3、修改文件中的数据
五、缓冲流
1、字节缓冲流(单个+多个)
字节缓冲流提高效率的原理
节约的是读和写的时候和硬盘打交道的时间
2、字符缓冲流
提高的效率不是很明显,但有两个很好用的方法
续写:
3、总结
六、转换流
把字节流转换成字符流
七、序列化流/对象操作输出流
八、反序列化流/对象操作输入流
细节:
如果修改javabean类,会报错,因为版本号改变了,
解决办法:固定版本号
(1)方法1:固定私有,static,final且long的serialVersionUID = 1L
(2) 方法2:利用idea
可能版本不同换了位置 不显示的可以在File > Settings > Editor > Inspections > JVM languages 下找到并勾选应用就可以了
如果某个变量不想序列化到本地,加关键字transient
如果在反序列化流时不知道有几个对象,就把ois.readObject()强转成ArrayList<自定义类>
九、打印流
打印流只有输出,没有读
字符打印
不加自动刷新的话要手动刷新才行,不然还在缓存里放着,不过close也会自动刷新
总结
十、解压缩流/压缩流
1、解压缩流
2、压缩流
(1)压缩单个文件
(2)压缩文件夹