Java基础知识 IO &&字节流

Java基础知识 IO &&字节流

1. IO
	1、IO:input和output两个单词的缩写,input是输入,output是输出
 	站在内存的角度看待方向,从其他设备进入内存的,都是输入,从内存到其他设备的,都是输出
 	I/O就是用于设备之间进行数据交互的对象所属的类型
2、java中操作设备设备之间数据传输的对象,都是IO流对象,这些对象所属的类型,都在io包中。
2.IO分类
	    1、 分类的方式有两种:按照功能可以分类,按照流向也可以分类
	    2、 按照功能分类:
	 	字节流:可以直接操作字节的流对象
	 	字符流:可以直接操作字符的流对象
	    3、 按照流向分类:
	 	输入流:其他设备流到内存的流对象
	 	输出流:内存流到其他设备的流对象
	    4、 IO流的体系结构,根据分类,有四种流对象的类型
	 	字节流:
	 	 	字节输入流:InputStream
	 	 	字节输出流:OutputStream
	  	字符流:
	 	 	字符输入流:Reader
	 	 	字符输出流:Writer
3.字节流
	    1、 可以直接操作字节信息的流对象
	    2、 根据流向,可以分成字节输入流和字节输出流
	    3、 顶层抽象父类分别是:InputStream 和 OutputStream
	    4、 根据交互设备的不同,有不同的具体子类
	InputStream
	    1、 字节输入流的顶层抽象父类
	    2、 常用的方法
			 	read():从当前的字节输入流中,获取一个字节
			 	read(byte[] arr):将arr.length个字节,读取到arr中
	    3、 InputStream是一个抽象类,不能直接创建对象,只能由子类创建对象
	FileInputStream
	    1、 InputStream的一个具体子类,用于和磁盘上的文件进行交互
	    2、 FileInputStream不仅可以一次读取一个字节,也可以一次读取很多个字节;不仅可以读取纯文本文件,也可以读取图片、视频、音频等非纯文本文件。
	    一切数据在计算机中都是以字节的形式在存储和计算
	    3、 构造方法:
			 	FileInputStream(File f):将File对象封装成字节输入流,将来可以读取这个文件中的信息
			 	FileInputStream(String path):将字符串封装成字节输入流,将来可以读取信息
	 	
	 	注意事项:无论是哪个构造方法,都只能封装文件的路径,封装文件夹的路径没有任何意义,因为文件夹本身没有任何数据,所以也不能使用流对象读取数据。
	    4、 两个常用方法:
			 	read():一次读取一个字节,返回值类型是int类型,原因要把返回的字节前面加上240,
			 	无论读取到的是负数还是整数,都会变成正数,只要是从文件中读取到的数据,都是整数;
			 	如果返回了-1,就说明不是从文件中读到的数据,而是整个方法专门准备的文件末尾的标记。
			 	说明:虽然每次调用该方法,但是返回的内容却不会相同,因为文件指针在不断向后移动。
			 	read(byte[] arr):一次读取多个字节,存储到字节数组中
		
	OutputStream   
	    1、 字节输出流的顶层抽象父类
	    2、 常用方法:
		 	write(int b):将一个字节信息写出到指定的设备中
		 	write(byte[] arr):将一个字节数组中的所有信息,写出到指定设备中
		 	write(byte[] arr, int offset, int len):将一个字节数组arr中的从offset索引开始,总共len个字节写出到指定的设备中。
	    3、 这个类是抽象类,不能直接创建对象
	FileOutputStream
	    1、 说明:可以将字节数据写出到指定的文件中
	    2、 构造方法:
		 	FileOutputStream(File f):将f描述的路径文件封装成字节输出流对象
		 	FileOutputStream(String path):将path描述的文件路径封装成字节输出流对象
		 	FileOutputStream  fos = new FileOutStream("1.txt",true);
		 	如果没有1.txt 虚拟机会先自动地创建1.txt文件,true为决定是否追加,不写默认覆盖; 
		 	字节流有自动刷新的功能;
		 	字符流不会自动刷新,需要手动刷新;
		 	flush();
		 	刷新完后需要手动的关闭;
		 	close();
	 		使用字节输出流写出数据,就进入到关联的文件中。
	    3、 注意事项:
		 	1、成员方法都来自于抽象父类
		 	2、写到磁盘上,存储的就是数字,既没有编码,也没有解码;如果使用文本编辑器读取这个文件,就会发生两步:先读取数据,通过编码表进行解码,让我们看到字符

4.文件拷贝
    1、 含义:
 	将一个文件中的数据,拷贝到另一个文件中
    2、 本质:
	 	从一个文件中,使用输入流,读取一个字节
	 	将这个字节,使用输出流,写出到另外一个文件中
5.文件拷贝效率提升
    1、 使用一个字节一个字节拷贝的方式,效率非常低:IO的次数过多,有多少个字节,就要IO两倍的次数
    2、 提升的思路:一次多读一些数据,一次多写出一些数据,使用FileInputStream中的read(byte[] arr)和FileOutputStream中的write(byte[] arr)。
    数组的大小可以准备成和文件一样样大。配合InputStream中的available方法可以获取源文件的字节个数,用于创建数组的大小。
    3、 数组属于内存的,内存的大小是有限的,如果文件过大,就无法创建大小相同的数组。
    4、 只能考虑使用小一些的数组,每次拷贝源文件的一部分,多拷贝几次。涉及的方法:
	 	InputStream中的read(byte[] arr):将数据读取到数组中,返回本次读到的有效字节的个数,
	 	如果返回值为-1,表示本次读到的有效字节个数为0,表示到达了文件末尾
	 	OutputStream中的write(byte[] arr):将数组中的所有数据,都写出到了目标文件中
	 	OutputStream中的write(byte[] arr, int offset, int len):将数组中的指定部分的数据,
	 	写出到目标文件中(在读取的时候,读到了多少有效字节,就将这么多有效字节写出到目标文件中),一般offset都选择0
    5、 注意事项:最终拷贝方案就是小数组
	 	1、数组的大小可以任意选择,数组越大,拷贝次数越少,拷贝的效率越高
	 	2、一般情况,数组的大小使用1024的整数倍,在jdk中喜欢使用1024*8大小作为缓冲区的大小。
6.InputStream类型中read()方法和read(byte[] arr)方法的比较
    1、 读取字节个数的区别:
	 	read()方法一次只能读取一个字节
	 	read(byte[] arr)方法一次可以读取多个字节,取决于数组的大小
    2、 读取到的字节信息存储的位置不同:
	 	read()读取到的文件字节信息是作为返回值进行返回的
	 	read(byte[] arr)读取到的字节信息,存储到参数数组arr中
    3、 返回值的含义不同:两个方法的返回值类型都是int类型
	 	read()方法返回的是读取的有效字节本身
	 	read(byte[] arr)方法的返回是读取到的有效字节的个数(返回值的取值范围:-1,1~arr.length)
7.高效缓冲流
    1、 BufferedInputStream和BufferedOutputStream
    2、 是包装类型:本身不具备读写的功能,只是在某个具体的流对象的基础上,对其进行加强,例如FileInputStream和FileOutputStream,原本效率较低,加强之后,就效率较高
    3、 构造方法:
	 	BufferedInputStream(InputStream is):将指定的具体的字节输入流传入构造方法的参数,形成一个高效版本的字节输入流
	 	BufferedOutputStream(OutputStream os):将指定的具体的字节输出流传入构造方法的参数,形成一个高效版本的字节输出流
    4、 使用:
 		这两个高效流还是字节流,还是InputStream和OutputStream,所以抽象父类中的那些方法仍然可以继续使用
    5、 原理:
	 	1、BufferedInputStream高效的原理:在该类型中准备了一个数组,存储字节信息,
	 	当外界调用read()方法想获取一个字节的时候,该对象从文件中一次性读取了8192个字节到数组中,
	 	只返回了第一个字节给调用者。将来调用者再次调用read方法时,
	 	当前对象就不需要再次访问磁盘,只需要从数组中取出一个字节返回给调用者即可,
	 	由于读取的是数组,所以速度非常快。当8192个字节全都读取完成之后,再需要读取一个字节,
	 	就得让该对象到文件中读取下一个8192个字节了。
	 	2、BufferedOutputStream高效的原理:在该类型中准备了一个数组,
	 	存储字节信息,当外界调用write方法想写出一个字节的时候,
	 	该对象直接将这个字节存储到了自己的数组中,而不刷新到文件中。
	 	一直到该数组所有8192个位置全都占满,该对象才把这个数组中的所有数据一次性写出到目标文件中。
	 	如果最后一次循环过程中,没有将数组写满,最终在关闭流对象的时候,也会将该数组中的数据刷新到文件中。
8.输出流中的close()flush()的区别
    1、 close方法会先调用flush方法
    2、 close方法用于流对象的关闭,一旦调用了close方法,那么这个流对象就不能继续使用了
    3、 flush只是将缓冲区中的数据,刷新到相应文件中,而不会将流对象关闭,可以继续使用这个流对象。但是如果flush方法使用过于频繁,那么丧失了缓冲区的作用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值