一.IO流
1.概念
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的类都在IO包中
流按流向分为两种:输入流,输出流。
流按操作类型分为两种:字节流与字符流。 字节流可以操作任何数据,字符流只能操作纯字符数据,比较方便。(字符流相当于字节流加上编码表,可变)
2.IO流常用父类
//最顶层的四个父类
字节流的抽象父类:
InputStream,OutputStream
字符流的抽象父类:
Reader, Writer
3.IO程序书写 //内存和硬盘通过IO联通
//使用的三步操作
1、使用前,导入IO包中的类
2、使用时,进行IO异常处理
3、使用后,释放资源
二.字节流
1.读取文件
创建FileInputStream对象,指定一个文件.文件必须存在,不存在则会抛出FileNotFoundException
使用read()方法可以从文件中读取一个字节.如果读取到文件末尾会读到-1
读取结束后需要释放资源,调用close()方法关闭输入流
FileInputStream fis = new FileInputStream("chu.txt");
int a;
while((a = fis.read())!= -1){ //文件结束标记-1
System.out.println(a);
}
fis.close(); //释放资源
问题:read()方法每次读到的是一个字节,为什么要返回int而不是byte
因为文件的结束标志为-1为int型的 byte在读取的时候会在前面补上24个0,有时候我们读到文件的-1时程序也不会结束,因为-1的补码加上24个0,就变成正数,写的时候再去掉24个0。
(因为字节流可以读取任意类型的文件如果读一个字节返回时byte类型的,在读的过程中如果可能会读到-1,如果读到byte类型的-1,返回也是byte类型的,循环就会结束,如果返回的是int类型的,程序就不会结束,不会丢失数据)
2.写出文件
创建FileOutputStream对象,指定一个文件.文件不存在会创建新文件,存在则清空原内容.如果需要追加,在构造函数中传入true.
使用write()方法可以向文件写出一个字节.
写出结束后同样需要调用close()
FileOutputStream file = new FileOutputStream("bbb.txt");//这个文件是可以不存在的,系统自动创建
file.write(97);
file.write(98);
file.close();
FileOutputStream file = new FileOutputStream("bbb.txt",true)//加上true,再添加就是追加,而不是清空
3.拷贝文件
可以从文件中逐个字节读取,逐个字节写出,但这样做效率非常低
我们可以定义一个数组作为缓冲区,一次读取多个字节装入数组,然后再一次性把数组中的字节写出1byte = 8bit
1、方式一
;
FileInputStream file = new FileInputStream("王菲 - 致青春.mp3");
FileOutputStream ofile=new FileOutputStream("copy致青春.mp3");
byte [] arr = new byte[1024];
int len;
while ((len = file.read(arr))!=-1){
ofile.write(arr,0,len);
}
file.close();
ofile.close();
2、方式二 (不建议使用,有时候需要占用的内存过大而溢出)
ileInputStream file = new FileInputStream("王菲 - 致青春.mp3");
FileOutputStream ofile=new FileOutputStream("copy致青春.mp3");
byte [] arr = new byte[file.available()];
file.read(arr);
ofile.write(arr);
file.close();
ofile.close();
3、方式三
FileInputStream fis = new FileInputStream("致青春.mp3");
BufferedInputStream bis = new BufferedInputStream(fis); //创建缓冲区输入流对象,对fis进行包装
FileOutputStream fos = new FileOutputStream("copy.mp3");
BufferedOutputStream bos = new BufferedOutputStream(fos); //创建缓冲区输出流对象,对fos进行包装
int b;
while((b = bis.read()) != -1) { //bis.read()会将将文件上的数据读到缓冲区中,再从缓冲里获取数据
bos.write(b); //bos.write(b)是先将字节写到缓冲区里,然后在从缓冲区中一起写出
}
bis.close();
bos.close();
4.常用方法
InputStream:
read() 读取一个字节
read(byte[]) 读取若干(数组长度)字节
available() 获取可读的字节数
close() 关闭流,释放资源
OutputStream:
write(int) 写出一个字节
write(byte[]) 写出数组中的所有字节
write(byte[],start,len);
close() 关闭流,释放资源
5.BufferedInputStream
BufferedInputStream内置了一个缓冲区(数组)
从BufferedInputStream中读取一个字节时
BufferedInputStream会一次性从文件中读取8192个,存在缓冲区中,返回给程序一个
程序再次读取时,就不用找文件了,直接从缓冲区中获取
直到缓冲区中所有的都被使用过,才重新从文件中读取8192个
6.BufferedOutputStream
BufferedOutputStream也内置了一个缓冲区(数组)
程序向流中写出字节时,不会直接写到文件,先写到缓冲区中
直到缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一次性写到文件里
字节流只读中文是,可能会读到半个中文
1、用字符流
2、byteArrayOutputStream
字节流只写中文,是可以写的,但是必须将字符串转黄成字节数组。
用拷贝是不会出现只读到半个中文的。
三.重点
1.拷贝文件
* a.使用FileInputStream和FileOutputStream,逐个字节拷贝
b.使用FileInputStream和FileOutputStream,定义一个大数组(length等于文件大小),一次性拷贝
c.使用FileInputStream和FileOutputStream,定义一个小数组(例如1024),多次拷贝
d.使用BufferedInputStream和BufferedOutputStream内置的缓冲区,逐个字节拷贝
2.标准化IO流操作的代码
a.finally嵌套
b.tryclose