javaSE复习之——IO流_文件字节流
FileInputStream概述
它是一个输入流,它的作用是从文件系统中的某个文件中获得输入字节,它是
InputStream
的子类
创建一个文件输入流
1 | FileInputStream fis = new FileInputStream("1.txt"); |
IO文件输入流的方法
- .read()
从输入流读取下一个字节返回这个字节的int值,文件结束标记是-1,也就是读到-1就读完这个文件了。
- .read(arr)
从输入流读取字节存到arr数组中,也就是内存中,返回读取到的字节数
- .available()
获取可以读的剩余字节数
为什么read()
方法读取一个字节返回的是int而不是字节类型的byte?
- 解答:
一个字节等于8个二进制位,也就是
-1的二进制位补码是1111 1111
,然后文件的底层都是以二进制形式存储的,这些文件的二进制中难免中途会遇到某个字节是1111 1111(八个一),如果read方法直接返回byte的话那么遇到这种情况就直接停止读取文件了,为了解决这个问题就直接返回int而不直接返回byte,因为在Java中一个int数据占4个字节,也就是占32个二进制位
,而read方法中从文件读取一个字节就在其二进制位前面加上24个0让其组成一个int类型数据返回
,这样就返回了一个255而不是返回1了,这样就可以保证数据的完整,而文件结束标记的-1它本身就是整数型所以不会受到影响。当然在使用输出流输出文件时write方法会自动去除int前面的24个零
。
FileOutputStream的概述
它是一个输出流,它的作用将指定字节写入此文件输出流,它是OutputStream的子类
输出流注意事项
1、输入流指定的文件不存在会报错,而输出流却不会,它是直接创建这个文件
2、虽然写出的是一个int类型的数据,但其实write方法会自动去除int数据的前3个8位2进制位
3、如果文件存在,那么就会先将文件内容清空,如果不要让他清空要追加,那么就在创建对象时第二个参数传入一个true
- 例子:
1
2
3
4
5
6
7
8
9
10
11
12
13 FileOutputStream fos = new FileOutputStream("1.txt", true);```
### IO文件输出流的方法
- .write()
将指定字节写入此文件输出流
- .write(arr)
将arr数组中的字节写到文件中
- .write(arr, off, len)
off为数组起始偏移量,也就是起始索引,通常0、len就是要写入数据的总长度
### 利用IO流进行文件拷贝例程之——`缓冲区拷贝`(单纯拷贝时推荐,中间需要对数据进行处理则使用带Buffered的封装类)FileInputStream fis = new FileInputStream("致青春.mp3"); //创建输入流对象,关联致青春.mp3
FileOutputStream fos = new FileOutputStream("copy.mp3");
//创建输出流对象,关联copy.mp3
//int len = fis.available();
//System.out.println(len);
byte[] arr = new byte[fis.available()];
//创建与文件一样大小的字节数组
fis.read(arr);
//将文件上的字节读取到内存中
fos.write(arr);
//将字节数组中的字节数据写到文件上
fis.close();
fos.close();
1 | ps:不推荐使用,因为一次性把所有字节都读下来放在内存中会导致占用内存过多,如果操作的是一个蓝光电影,就会`内存溢出`。 |
byte b[] = new byte[8192];
//缓冲区一定要为1024的整数倍
int len;
while ((len = fis.read(b)) != -1) {
fos.write(b, 0, len);
}
1 |
|
FileInputStream fis = new FileInputStream("致青春.mp3");
//创建输入流对象,关联致青春.mp3
FileOutputStream fos = new FileOutputStream("copy.mp3");
//创建输出流对象,关联copy.mp3
int b;
//在不断的读取每一个字节
while((b = fis.read()) != -1) {
fos.write(b);
//将每一个字节写出
}
fis.close();
//关流释放资源
fos.close();
1 | ps:他有个缺点,那就是效率非常的慢,因为需要一个字节一个字节的读然后写。 |
FileInputStream fis = new FileInputStream("致青春.mp3");
//创建文件输入流对象,关联致青春.mp3
BufferedInputStream bis = new BufferedInputStream(fis);
//创建缓冲区对fis装饰
FileOutputStream fos = new FileOutputStream("copy.mp3");
//创建输出流对象,关联copy.mp3
BufferedOutputStream bos = new BufferedOutputStream(fos);
//创建缓冲区对fos装饰
int b;
while((b = bis.read()) != -1) {
bos.write(b);
}
bis.close();
//只关装饰后的对象即可
bos.close();
1 |
|
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("aaa.txt");
fos = new FileOutputStream("bbb.txt");
int b;
while((b = fis.read()) != -1) {
fos.write(b);
}
} finally {
try {
if(fis != null)
fis.close(); //能关掉一个算一个
}finally {
if(fos != null)
fos.close();
}
}
1 |
|
try(
FileInputStream fis = new FileInputStream("aaa.txt");
FileOutputStream fos = new FileOutputStream("bbb.txt");
MyClose mc = new MyClose();
){
int b;
while((b = fis.read()) != -1) {
fos.write(b);
}
}
```
拓展知识之——文件加密
- 原理
我们知道2 ^ 3 = 1这是个异或运算也就是0010 ^ 0011 = 0001.
那么我们就可以
源数据 ^ 密文 = 加密后的数据
加密后的数据 ^ 密文 = 源数据
通过异或这个原理,我们可以知道用
相同数异或两编,那么原来的数就会回来
,这样我们就可以再写出字节流时,把写出的数据进行一遍异或运算,这样就达到了加密的效果,解密就是读取的时候再异或**同样的数
**,这样原来的数据就回来了,不过这样加密数据为了代码更加简洁就需要使用Buffered的字节流对象,不能自己创建缓冲区了。