IO流(字节流)

在这里插入图片描述

1.概念

IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式,Java用于操作流的类都在IO包中

2.分类

流按流向分为两种:输入流,输出流。
流按操作类型分为两种:

  • 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
  • 字符流 : 字符流只能操作纯字符数据,比较方便。【字符流必不可少,当处理文字符号时,必须将字节流转化为字符流,不然会出现乱码】
3.常用父类
  • IO流常用父类字节流的抽象父类:InputStream OutputStream
    具体实现 Input Stream为抽象类,不能直接创建,这里使用实现它的一个子类FileInputStream
    • read()方法就像是一个指针,每次读取后都会向后移动一位,以数值(-1)为结束标志
      在这里插入图片描述
FileInputStream fileInputStream = new FileInputStream("name.txt");
int len;
while((len = fileInputStream.read()) != -1) {
    System.out.print(len);
}

同样OutputStream也是一个抽象类,这里使用FileOutputStream为例,进行演示
FileOutputStream在创建对象的时候如果没有则新创建一个,如果有则清空文件中的数据,如果想续写,则可以在构造时第二个参数传入true

FileOutputStream outputStream = new FileOutputStream("text.txt");
outputStream.write(97); //数值为int型,但是在文件中存储的一个字节,会自动删除前三个8位
outputStream.write(98);
outputStream.write(99);
outputStream.close();

在这里插入图片描述

读取一个数据字节,为什么不使用byte作为read()的返回值?

(1)因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111
那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上
24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型

  • 字符流的抽象父类:Reader Writer
4.使用注意事项

(1)IO程序书写使用前,导入IO包中的类
(2)使用时,进行IO异常处理
(3)使用后,释放资源

实例演示(拷贝文件)

示例一:

  • 复制图片
    缺点:效率低,一个一个字节读取
FileInputStream fileInputStream = new FileInputStream("student.png");
FileOutputStream fileOutputStream = new FileOutputStream("copy.png");
int b;
while ((b = fileInputStream.read()) != -1) {
    fileOutputStream.write(b);
}
fileInputStream.close();
fileOutputStream.close();

示例二:

  • 复制音频文件【用图片复制的方法效率低下】(字节数组拷贝音频文件)
    缺点:占用内存
FileInputStream fileInputStream = new FileInputStream("four.mp3");
FileOutputStream fileOutputStream = new FileOutputStream("copy.mp3");
byte[] array = new byte[fileInputStream.available()];//fileInputStream.available()方法返回文件的大小
fileInputStream.read(array);
fileOutputStream.write(array);
fileInputStream.close();
fileOutputStream.close();

示例三(经常使用)【定义小数组法】
当数组容量比较小时,这时使用如下方法会出现弊端
在这里插入图片描述
比如:(原文件)
在这里插入图片描述
(复制后文件)
在这里插入图片描述

FileInputStream fileInputStream = new FileInputStream("text.txt");
    FileOutputStream fileOutputStream = new FileOutputStream("tet.txt");
    byte[] arr = new byte[2];//每次读取两个字符
    int len;
    while((len = fileInputStream.read(arr)) != -1) {
     //len记录读取的有效字符个数,如果没有传入参数,则返回读取字符的码表值
        fileOutputStream.write(arr);
    }
    fileInputStream.close();
    fileOutputStream.close();
}

在这种情况下推荐使用
在这里插入图片描述
改写为:在这里插入图片描述


  • 进一步改进(最常见的使用方法
FileInputStream fileInputStream = new FileInputStream("text.txt");
FileOutputStream fileOutputStream = new FileOutputStream("tet.txt");
byte[] arr = new byte[1024 * 8]; 
//因为计算机进制为1024,一般数组的大小使用1024的整数倍
int len;
while((len = fileInputStream.read(arr)) != -1) { //len记录读取的有效字符个数,如果没有传入参数,则返回读取字符的码表值
    fileOutputStream.write(arr,0,len);
}
fileInputStream.close();
fileOutputStream.close();

方式四:(带缓冲区)
优点:效率高,但是略低于定义小数组法(即方式三),但是不需要自己创建数组,底层系统已经创建好数组。
【使用BufferInputStream和BufferedOutputStream,相当于对InputStream和OutputStream的包装,关闭流时相关的InputStream和OutputStream也随之关闭】

	FileInputStream fileInputStream = new FileInputStream("text.txt");
	FileOutputStream fileOutputStream = new FileOutputStream("teet.txt");
	BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
	BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
	int b;
	while ((b = bufferedInputStream.read()) != -1) {
	 	bufferedOutputStream.write(b);
	}
	bufferedInputStream.close();//随之相关的fileInputStream也关闭
	bufferedOutputStream.close();
}

原理图:
在这里插入图片描述
使用InputStream和OutputStream原理图
在这里插入图片描述

flush()和close()的区别

flush()是清除缓存区,close()是清除缓存区后关闭流
比如字节数组每次读取1024个字节后,写入输出流,当最后一次写入不足1024个字节后,使用close()方法会写出剩余的内容,然后关闭流。

  • flush()是刷新缓存区的,刷新之后可以再次写出
  • close()是关闭流释放资源,当是带缓存区的流对象时,在关闭之前会刷新缓存区,在关闭流释放资源,关闭后不能再写出。
字节流读写中文
  • 字节流读字符,由于标点符号以及中文字节问题,使用字节流读取中文字符会出现乱码,所以一般不使用字节流读取中文字符。
  • 字节流写入中文,必须转化为字节数组的形式。
FileOutputStream fileOutputStream = new FileOutputStream("teet.txt");
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
bufferedOutputStream.write("好好学习".getBytes());
bufferedOutputStream.close();
  • 图片加密
    当写入文件时异或一个数,这个数就是密钥,解密时只需要再次异或就可以
FileInputStream fileInputStream = new FileInputStream("copy.png");
FileOutputStream fileOutputStream = new FileOutputStream("newne.png");
byte[] arr = new byte[1024];
int b;
while ((b = fileInputStream.read(arr)) != -1) {
    fileOutputStream.write(b ^ 123);
}
fileInputStream.close();
fileOutputStream.close();

解密时只需要对加密文件再次异或就可以。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值