IO流(字节流)

1 FileInputStream
2 FileOutputStream
3 BufferedInputStream
4 BufferedOutputStream

1 FileInputStream

  • 字节流的概念:字节流读取的都是文件中的二进制数据,读取到的二进制数据不会经过任何的处理。

  • InputStream 是所有输入字节流的基类(抽象类)

  • FileInputStream 是读取文件数据的输入字节流

使用FileInputStream读取文件数据的步骤:

  1. 找到目标文件
  2. 建立数据的输入通道
  3. 读取文件中的数据
  4. 关闭资源

方法1和方法3已经被淘汰了,推荐使用方法4,理论上效率更高。

public class Demo1 {
	public static void main(String[] args) throws IOException {
		readTest4();
	}
	
	// 方式4:使用缓冲数组配合循环读取。
	public static void readTest4() throws IOException {
		// 1.找到目标文件
		File file = new File("G:\\a.txt");
		// 2.建立数据的输入通道
		FileInputStream fileInputStream = new FileInputStream(file);
		// 3.读取文件中的数据
		byte[] buf = new byte[4]; //  缓冲数组的长度一般是1024的倍数,符合计算机的处理单位。理论上缓冲数组越大,效率越高。
		int length = 0; // 保存每次读取到的字节数
		while((length = fileInputStream.read(buf)) != -1) { // read方法如果读取到文件的末尾,那么就会返回-1表示
			System.out.print(new String(buf, 0, length));
		}
		// 4.关闭资源
		fileInputStream.close();
	}	

	// 方式3:使用缓冲数组读取	 缺点:无法完整读取一个文件的数据。
	public static void readTest3() throws IOException {
		// 1.找到目标文件
		File file = new File("G:\\a.txt");
		// 2.建立数据的输入通道
		FileInputStream fileInputStream = new FileInputStream(file);
		// 3.读取文件中的数据
		byte[] buf = new byte[1024]; // 相当于超市里的购物车
		int length = fileInputStream.read(buf); // 如果使用read读取数据传入字节数组,那么数据是存储到字节数组中的,而这时read方法返回值表示本次读取了几个字节数据到字节数组中。
		System.out.println(length);
		String content = new String(buf, 0, length); // 使用字节数组构建字符串
		System.out.println("内容:" + content);
		// 4.关闭资源
		fileInputStream.close();
	}	

	// 方式2:使用循环读取文件的数据。
	public static void readTest2() throws IOException {
		long startTime = System.currentTimeMillis();
		// 1.找到目标文件
		File file = new File("G:\\a.txt");
		// 2.建立数据的输入通道
		FileInputStream fileInputStream = new FileInputStream(file);
		// 3.读取文件中的数据
		int content = 0; // 声明该变量用于存储读取到的数据
		while((content = fileInputStream.read()) != -1) { // read方法如果读取到文件的末尾,那么就会返回-1表示
			System.out.print((char)content);
		}
		long endTime = System.currentTimeMillis();
		System.out.println(endTime - startTime);
	}

	// 读取方式1的缺陷:无法将一个文件的数据完整读取。
	public static void readTest1() throws IOException {
		// 1.找到目标文件
		File file = new File("G:\\a.txt");
		// 2.建立数据的输入通道
		FileInputStream fileInputStream = new FileInputStream(file);
		// 3.读取文件中的数据
		int content = fileInputStream.read(); // read() 读取一个字节的数据,把读取的数据返回。
		System.out.println("读到的内容是:" + (char)content); // a
		// 4.关闭资源	实际上就是释放资源
		fileInputStream.close();
	}
}
  • 问题1:读取完一个文件的数据时,不关闭资源有什么影响?
    ​资源一旦使用完毕应该马上释放,否则其他的程序无法对该资源文件进行操作。
  • 问题2:方式4中,当缓冲数组的长度为4时,就会对文件中的数据每4个字节一读取。文件中的4个字节存储到缓冲数组后,那么下一次存储的方式是怎样的?
    ​是以覆盖的方式存储的。假如文件中的数据为:aaaabbb,构建字符串时若没有指定长度的话,读取到的完整数据就会是:aaaabbba

2 FileOutputStream

  • OutputStream 是所有输出字节流的父类(抽象类)
  • FileOutputStream 是向文件输出数据的输出字节流

FileOutputStream的使用步骤:

  1. 找到目标文件。
  2. 建立数据的输出通道。
  3. 把数据转成字节数据写出。
  4. 关闭资源。

FileOutputStream要注意的细节

  1. 使用FileOutputStream写数据时,如果目标文件不存在,那么自动创建目标文件对象。
  2. 使用FileOutputStream写数据时,如果目标文件已存在,那么会先清空目标文件中的数据,然后再写入数据。
  3. 使用FileOutputStream写数据时,如果目标文件已存在,需要在原来数据基础上追加数据,就要使用:new
    FileOutputStream(file, true)构造函数,第二个参数为true。
  4. 使用FileOutputStream的write方法写数据时,虽然接收到的是一个int类型(32位)的数据,但是真正写出的只是一个字节(8位)的数据,只把低八位的数据写出,其他24位数据全部丢弃
public class Demo1 {
	public static void main(String[] args) throws IOException {
		writeTest2();
	}
	
	/**
	* 使用字符数组把数据写出
	*/
	public static void writeTest2() throws IOException {
		// 找到目标路径
		File file = new File("G:\\a.txt");
		
		// 建立数据的输出通道
//		FileOutputStream fileOutputStream = new FileOutputStream(file);
		FileOutputStream fileOutputStream = new FileOutputStream(file, true);
		
		// 把数据写出
//		String data = "hello world";
		String data = "\r\nhello world";
		fileOutputStream.write(data.getBytes()); // 将字符串转换为字节数组写出。
		
		// 关闭资源
		fileOutputStream.close();
	}
	
	/**
	* 每次只能写出一个字节的数据
	*/
	public static void writeTest1() throws IOException {
		// 找到目标路径
		File file = new File("G:\\a.txt");
		
		// 建立数据的输出通道
		FileOutputStream fileOutputStream = new FileOutputStream(file);
		
		// 把数据写出
		fileOutputStream.write('h'); // 传入的是字符类型,会自动转换成int类型
		fileOutputStream.write('e');
		fileOutputStream.write('l');
		fileOutputStream.write('l');
		fileOutputStream.write('o');
		
		// 关闭资源
		fileOutputStream.close();
	}
}
/**
* 需求:拷贝一张图片
*/
public class Demo3 {
	public static void main(String[] args) throws IOException {
		copy();
	}
	
	public static void copy() throws IOException {
		// 找到目标文件
		File inFile = new File("G:\\1.jpg");
		File destFile = new File("F:\\1.jpg");
		
		// 建立数据的输入输出通道
		FileInputStream fileInputStream = new FileInputStream(inFile);
		// 每创建一个FileOutputStream时,默认情况下,FileOutputStream的指针会指向文件的开始位置。而当FileOutputStream创建后,每写出一次数据,指针都会移动到文件的末尾处。因此这里是没有必要加true的。
		FileOutputStream fileOutputStream = new FileOutputStream(destFile);
		
		// 建立缓冲数组,边读边写
		byte[] buf = new byte[1024];
		int length = 0;
		while((length = fileInputStream.read(buf)) != -1) {
			fileOutputStream.write(buf, 0, length); // 如果不指定长度,拷贝过去的图片就很可能比源图片大!
		}
		
		// 关闭资源	原则:先开后关,后开先关
		fileOutputStream.close();
		fileInputStream.close();
	}
}

3 BufferedInputStream

  • 输入字节流的体系:
    --------| InputStream 输入字节流的基类(抽象类)
    --------------| FileInputStream 读取文件数据的输入字节流
    --------------| BufferedInputStream 缓冲输入字节流。缓冲输入字节流的出现主要是为了提高读取文件的效率。其实该类内部只不过是维护了一个8KB的字节数组而已

注意:凡是缓冲流都不具备读写文件的能力

使用BufferedInputStream的步骤:

  1. 找到目标文件
  2. 建立数据的输出通道
  3. 建立缓冲输入字节流
  4. 关闭资源

备注:使用缓冲输入字节流(BufferedInputStream)读取数据和创建字节数组使用数据输入字节流(FileInputStream)读取效率差不多,一般都习惯使用FileInputStream读取。

public class Demo1 {
	public static void main(String[] args) throws IOException {
		readTest2();
	}
    
	public static void readTest2() throws IOException {
		// 找到目标文件
		File file = new File("G:\\a.txt");
        
		// 建立数据的输入通道
		FileInputStream fileInputStream = new FileInputStream(file);
		// 建立缓冲输入字节流
		// 疑问1:为什么创建BufferedInputStream时需要传递FileInputStream?因为BufferedInputStream本身不具备读文件的能力,所以需要借助FileInputStream来读取文件中的数据。
		BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
        
		// 读取文件数据
		int content = 0;
		// 疑问2:BufferedInputStream出现的目的是为了提高读取文件的效率,但是BufferedInputStream的read方法每次只读取一个字节的数据,而FileInputStream的read方法每次也是读取一个数据,那么BufferedInputStream的高效率从何而来?
		// 根本原因是BufferedInputStream在内存中维护了一个8KB的缓冲数组,文件中的数据会先填充到该缓冲数组中,然后一个一个的读取;而FileInputStream是在硬盘中一个一个的直接读取数据的,所以BufferedInputStream的效率要高得多。
		while((content = bufferedInputStream.read()) != -1) {
			System.out.print((char)content);
		}
        
		// 关闭资源
		bufferedInputStream.close(); // 调用BufferedInputStream的close方法实际上关闭的是FileInputStream。
	}
    
	// 读取文件时我们都会使用缓冲数组读取。效率会更高
	public static void readTest1() throws IOException {
		File file = new File("G:\\a.txt");
		FileInputStream fileInputStream = new FileInputStream(file);
		byte[] buf = new byte[1024*8];
		int length = 0;
		while((length = fileInputStream.read(buf)) != -1) {
			System.out.println(new String(buf, 0, length));
		}
		fileInputStream.close();
	}
}

4 BufferedOutputStream

  • 输出字节流体系:
    --------| OutputStream 所有输出字节流的基类 抽象类
    --------------| FileOutputStream 向文件输出字节的输出字节流
    --------------| BufferedOutputStream 缓冲输出字节流。缓冲输出字节流出现的目的是为了提到写数据的效率。 内部也维护了一个8KB的字节数组

使用BufferedOutputStream的步骤:

  1. 找到目标文件
  2. 建立数据的输出通道
  3. 建立缓冲输出字节流对象
  4. 将数据写出
  5. 将缓冲数组中的数据写到硬盘上

BufferedOutputStream要注意的细节:

  • 使用BufferedOutputStream写数据时,它的write方法会先把数据写到它内部维护的缓冲字节数组中,如果需要将数据写到硬盘上,就要调用flush方法或者close方法,或者是当内部维护的字节数字填满数据时,会自动写到硬盘上
public class Demo2 {
	public static void main(String[] args) throws IOException {
		// 找到目标文件
		File file = new File("G:\\a.txt");
		
		// 建立数据的输出通道
		FileOutputStream fileOutputStream = new FileOutputStream(file);
		// 建立缓冲输出字节流对象
		BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
		
		// 将数据写出
		bufferedOutputStream.write("hello world".getBytes());
		// 将缓冲数组中的数据写到硬盘上
//		bufferedOutputStream.flush();
		bufferedOutputStream.close(); // 其实调用的FileOutputStream的close方法。close方法内部会先调用flush方法,然后再关闭。
	}
}
/**
* 需求:使用缓冲输入输出字节流拷贝一个图片
*/
public class Demo3 {
	public static void main(String[] args) throws IOException {
		copyImage();
	}
	public static void copyImage() throws IOException {
		// 找到目标文件
		File inFile = new File("G:\\1.jpg");
		File outFile = new File("F:\\1.jpg");
		
		// 建立数据输入输出通道
		FileInputStream fileInputStream = new FileInputStream(inFile);
		FileOutputStream fileOutputStream = new FileOutputStream(outFile);
		// 建立缓冲输入输出流
		BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);	
		BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
		
		// 边读边写
		int content = 0;
		while((content = bufferedInputStream.read()) != -1) {
			bufferedOutputStream.write(content);
		}
		
		// 关闭资源
		bufferedOutputStream.close();
		bufferedInputStream.close();
	}
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下 4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值