Day19
1 IO概述
- 概述:IO是Input和Output的缩写。
输入、输出。数据的输入和数据的输出。 - 输入输出的概念:
数据的输入和输出相对于运行内存来说,数据从其他设备进入到运行内存就是输入,数 据从运行内存到其他设备就是输出。
注意:
IO不是一个类型,而是描述数据输出和输入的概念。
凡是操作数据输入和输出的类型,都属于IO - 分类:
按照功能分类:
字节流:控制字节信息输入和输出
字符流:控制字符信息的输入和输出
按照流向分类:
输入流:控制信息从其他设备到运行内存
输出流:控制信息从运行内存到其他设备 - 具体分类:
字节输入流:InputStream
字节输出流:OutputStream
字符输入流:Reader 读者
字符输出流:Writer 作者 写者
2 字节流
- 概述:用来操作字节信息输入内存和输出内存
- 字节输入流InputStream 字节输出流OutputStream
2.1 InputStream
-
概述:字节输入流,本类是一个抽象类,不能直接创建对象,需要通过子类创建
-
方法:
read() :从流中读取一个字节信息,将读取的信息进行返回。读取的是一个字节,接 收的是一个int。因为读取一个字节之后,在这个字节前面强制加上24个0,强制变为一个int数
目的:如果不转为int,读取了-1,可能是到达文件末尾,也可能是读取的字节,无法区分,所以为了区分-1是到达文件末尾,就将读取的字节强制变为了int(正数),下次读取到-1之后,表示的肯定是到达文件末尾了。read(byte[] b) :
从流对象中一次读取b.length个字节
将读取的信息保存在数组中,返回的是读取的个数read(byte[] b, int off, int len) :
从流中读取指定长度的数据到数组中
将读取的信息保存在数组中,返回的是读取的个数available() :
将流中还没有读取的字节个数进行返回
close() :
关闭流资源
2.2 FileInputStream
- 概述:属于字节输入流的子类,该类的对象可以将磁盘上的文件数据读取到运行内存中
- 构造方法:
(1)FileInputStream(File file):将file文件对象封装为文件字节输入流对象
(2)FileInputStream(String str) :将str字符串所描述的文件封装为字节输入流对象 - 注意事项:
在创建对象时,传入的file对象和字符串,对应的必须是一个文件,不能是一个文件夹。
代码
package dems2_in_out;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
public class Demo01 {
public static void main(String[] args) throws IOException {
// FileInputStream fis2 = new FileInputStream(new File("day19/src/a.txt"));
FileInputStream fis = new FileInputStream("day19/src/a.txt");
byte[] bs = new byte[10];
//将读取的字节保存在数组中
//可以决定从数组的哪一个位置开始保存
//可以决定读取几个字节
int len = fis.read(bs, 2, 3);
System.out.println(len);
System.out.println(Arrays.toString(bs));
}
private static void read2(FileInputStream fis) throws IOException {
byte[] bs = new byte[10];
//返回的是读取的字节个数
//将读取的字节,保存在一个数组中
int len = fis.read(bs);
System.out.println(Arrays.toString(bs));
System.out.println(len);
}
private static void read1(FileInputStream fis) throws IOException {
//一次读取一个字节,将读取的字节返回 如果到达文件末尾返回-1
System.out.println((char) fis.read());
System.out.println((char) fis.read());
System.out.println((char) fis.read());
System.out.println((char) fis.read());
System.out.println(fis.read());
}
}
package dems2_in_out;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Demo02 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("day19/src/a.txt");
//使用循环读取文件中的所有字节
//如果读取的字节为-1,表示到达末尾,不再读取,如果不是-1,表示读取到了数据,就打印
int i;
while((i = fis.read()) != -1){
System.out.println((char)i);
}
//返回文件中剩余的字节个数
System.out.println(fis.available());
//关闭流资源
fis.close();
}
}
2.3 OutPutStream
- 概述:字节输出流,将字节信息从内存中写出到其他设备。也是一个抽象类,需要通过 子类创建对象。
- 方法:
函数 | 解释 |
---|---|
write(int b) | 将一个字节信息写出内存 |
write(byte[] b) | 将一个数组中的信息写出内存 |
write(byte[] b, int off, int len) | 将数组中的一部分信息写出内容 |
close() | 关闭流资源 |
2.4 FileOutputStream
- 概述:文件字节输出流,将字节信息从内存中写出到目标磁盘文件中。
- 构造方法:
函数 | 解释 |
---|---|
FileOutputStream(File file) | 将file对象封装为一个字节输出流对象 |
FileOutputStream(String name) | 将name字符串对应的文件封装为字节输出流对象 |
FileOutputStream((File file,boolean b) | 将name字符串对应的文件封装为字节输出流对 象,如果后面的值为false,表示替换写入信息 |
FileOutputStream(String name,boolean b) | 将name字符串对应的文件封装为字节输出 流对象,如果后面的值为true,表示追加写入信息 |
代码
package dems2_in_out;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo03 {
public static void main(String[] args) throws IOException {
//创建一个文件字节输出流对象
FileOutputStream fos = new FileOutputStream("day19/src/b.txt");
//写出一个字节
fos.write(97);
fos.write('b');
byte[] bs = {99,100,101};
//将数组中的字节全部写出
fos.write(bs);
byte[] bs2 = {'f','g','k','n'};
//将数组中的一部分字节写出
fos.write(bs2,2,2);
fos.close();
}
}
2.5 文件的拷贝
-
概述:将一个文件进行复制
-
思路:
先利用字节输入流读取源文件中的信息,读取之后,再利用字节输出流将读取的信息写 出到另一个文件中。 -
图示:
-
使用字节流拷贝文件,可以拷贝任何类型的文件(图片,视频,音频,只要是一个文件底层都是通过字节来存储的。)
代码
package dems2_in_out;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo05 {
public static void main(String[] args) throws IOException {
//创建一个字节输入流
FileInputStream fis = new FileInputStream("day19/src/a.txt");
//创建一个字节输出流
FileOutputStream fos = new FileOutputStream("day19/src/acopy.txt");
int i;
//使用循环读取源文件字节
while((i = fis.read()) != -1){
//将读取的字节写出到另一个文件
fos.write(i);
}
//关流
fis.close();
fos.close();
}
}
2.6 文件拷贝效率的提升
- 问题:
使用字节输入流和输出流可以完成文件的拷贝,如果文件过大,导致拷贝的速度比较慢。
如果使用正常方式拷贝,一个字节需要IO两次。 - 解决方案1:
可以一次多读几个字节,一次多写出几个字节
read(byte[] bs) wirte(byte[] bs);
使用数组拷贝有一个问题:
数组在运行内存中开辟空间的,如果数组的空间开辟过大,运行内存的空间就会被 占用太多,就导致整个计算机执行效率下降。 - 解决方案2:
使用小数组拷贝
使用小数组拷贝注意:
当前这一次读几个直接,就应该写出几个字节,避免多写出数据
read(byte[] bs) write(byte[] bs,int off,int len)
数组大小最好保持在:1024的整数倍即可 1024*8
代码
package dems2_in_out;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo06 {
public static void main(String[] args) throws IOException {
test01();
}
//使用小数组拷贝:提升拷贝的效率
private static void test01() throws IOException {
//创建一个字节输入流
FileInputStream fis = new FileInputStream("E:\\01_0803就业班\\day18\\06.LinekHashMap特点.mp4");
//创建一个字节输出流
FileOutputStream fos = new FileOutputStream("E:\\01_0803就业班\\day18\\06.LinekHashMap特点2222.mp4");
byte[] bs = new byte[1024*8];
int len;
while((len = fis.read(bs)) != -1){
fos.write(bs,0,len);
}
fis.close();
fos.close();
}
}
2.7 高效缓冲字节流
- 高效缓冲字节输入流:BufferedInputStream
- 高效缓冲字节输出流:BufferedOutPutStream
- 概述:这两个类型是包装类型,本类的对象不能读取和写出数据,但是这两个类型可以 对基础的流对象进行加强(包装),加强之后,可以默认一次读取多个数据,写出多个 数据,因为这两个类型中都维护了一个数组,来完成文件的拷贝。
- 构造方法:
BufferedInputStream(InputStream in)
:将基础的字节输入流对象进行包装成为一个高效 字节输入流
BufferedOutputStream(OutputStream out)
:将基础的字节输出流对象进行包装
5、图示:
代码
package dems2_in_out;
import java.io.*;
public class Demo07 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("E:\\01_0803就业班\\day18\\06.LinekHashMap特点.mp4");
FileOutputStream fos = new FileOutputStream("E:\\01_0803就业班\\day18\\06.LinekHashMap特点333.mp4");
//创建一个高效缓冲字节输入流
BufferedInputStream bis = new BufferedInputStream(fis);
//创建一个高效缓冲字节输出流
BufferedOutputStream bos = new BufferedOutputStream(fos);
int i;
//读取
while((i = bis.read()) != -1){
//写出
bos.write(i);
}
//关流
bis.close();
//使用高效缓冲字节输出流之后,需要关闭系统资源
//获取使用刷新方法 bos.flush();
bos.close();
}
}
2.8 close和flush的区别
- close方法作用:
(1)可以将数据从缓冲区中刷新到目标文件中
(2)可以关闭流资源 - flush方法作用:
(1)只能将数据从缓冲区刷新到目标文件中 - 两者关系:
在使用close方法关闭流资源之前,系统会默认调用flush方法先刷新数据