IO流技术:看资源释放的三种强大的封装方法 & 字节数组流的使用

本篇将紧接上篇,同样以实现文件拷贝为例,探讨字节数组流ByteArrayInputStream 和 ByteArrayOutputStream 的使用方法,以及如何对资源释放进行封装,使我们处理资源释放问题时更加便捷。

一、概述

  • 文件存储在硬盘上,Java虚拟机无权访问,需要借助操作系统来访问和操作,并在操作完成后通知操作系统释放资源。
  • 而对于存有字节内容的字节数组,Java虚拟机可以直接访问。存储资源的内存可以在网络上,也可以在远程服务器等地方,关于资源的释放由Java内部的GC(垃圾自动回收机制)处理。
  • 所有对象都可以转为字节数组,使得网络传输等操作更加方便。

二、字节数组流的使用

ByteArrayOutputStream

我们先写入内容,再输出。

ByteArrayInputStream

使用ByteArrayInputStream要将数据准备成字节数组,可新创建一个字节数组。

代码

对接流实现文件与字节数组输入输出的转换为例:

1、图片到字节数组

文件输入流-字节数组输出流

  • 文件到程序:FileInputStream
  • 程序到字节数组:ByteArrayOutputStream

2、字节数组到图片

字节数组输入流-文件输出流

  • 字节数组到程序:ByteArrayInputStream
  • 程序到文件:FileOutputStream

注意:文件需要释放,字节数组流无需释放

主程序入口:

public static void main(String[] args) {
		//图片转成字节数组
		byte[] datas = fileToByteArray("BSandCS.png");
		System.out.println(datas.length);
		//字节数组转成图片
		byteArrayTofile(datas,"dest.png");
	}

图片读取到字节数组:

public static byte[] fileToByteArray(String filePath){
		//1、创建源
		File src = new File(filePath);
		byte[] dest = null;
		//2、选择流
		InputStream is=null;
		ByteArrayOutputStream os = null;
		try {
			is = new FileInputStream(src);
			os = new ByteArrayOutputStream();
			//3、传输操作:读
			byte[] flush = new byte[1024*10];  //缓冲容器
			int len=-1;   //接收长度
			while((len=is.read(flush))!=-1){
				os.write(flush,0,len);  //写出到字节数组中
			}
			//刷新一下
			os.flush();
			//获取数据
			dest = os.toByteArray();
			return dest;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{     //考虑异常处理,加上finally
			//4、释放资源
			try {
				if(null!=is){  
				is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

字节数组写出到图片:

public static void byteArrayTofile(byte[] src,String filePath){
		//1、创建流
		File dest = new File(filePath);
		//2、选择流
		InputStream is=null;
		FileOutputStream os=null;
		try {
			is = new ByteArrayInputStream(src);
			os = new FileOutputStream(dest);
			//3、传输操作:读
			byte[] flush = new byte[1024];  //缓冲容器
			int len=-1;   //接收长度
			while((len=is.read(flush))!=-1){
				os.write(flush,0,len);
			}
			os.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{     
			try {
				if (null != os) {
					os.close();
				} 
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

文件拷贝功能的实现举例:

public class FileUtils {
	public static void main(String[] args) {
		//文件到文件
		try {
			InputStream is = new FileInputStream("abc.txt");
			OutputStream os = new FileOutputStream("abc_copy.txt");
			copy(is,os);
		} catch (Exception e) {
			e.printStackTrace();
		}
		//文件到字节数组
		byte[] datas = null;
		try {
			InputStream is = new FileInputStream("abc.txt");
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			copy(is,os);
			datas = os.toByteArray();
			System.out.println(datas.length);
		} catch (Exception e) {
			e.printStackTrace();
		}
		//字节数组到文件
		try {
			InputStream is = new ByteArrayInputStream(datas);
			OutputStream os = new FileOutputStream("abc_copy.txt");
			copy(is,os);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    //对接输入输出流
	public static void copy(InputStream is,OutputStream os){
		try{
			//操作:读入与写出内容
			byte[] flush = new byte[1024];  //缓冲容器
			int len=-1;   //接收长度
			while((len=is.read(flush))!=-1){
				os.write(flush,0,len);
			}
			//刷新一下
			os.flush();
		}catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			close1(is,os);
		  //close2(is,os);
		}
	}
}

其中,close(is,os); 和 closed(is,os); 是我们接下来要探讨的两种实现释放资源的封装方法。

三、资源释放的封装

方法一

public static void close1(InputStream is,OutputStream os){
		try {
			if (null!=os) {
			os.close();
			} 
		} catch (Exception e) {
			e.printStackTrace();
			}
		//分别关闭:先打开的后关闭,可以保证目的地接收数据的准确性
		try {
			if(null!=is){  
			is.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
}

方法二

这里可变参数和数组功能是一样的,可关闭多个流,更灵活。

public static void close2(Closeable...ios){    
		for(Closeable io:ios){
			try {
				if(null!=io){  
				io.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
	  }
}

方法三

在Java版本1.7之后可以不用手动释放资源,用try…with…resource,将声明与初始化写入 try () 中,删去 finally { } ,让操作系统自动释放资源。具体操作如下:

try (InputStream is = new FileInputStream("abc.txt");
				OutputStream os = new FileOutputStream("abc_copy.txt");) {
		//具体操作:写入与取出
	} catch (FileNotFoundException e) {
			e.printStackTrace();
	} catch (IOException e) {
			e.printStackTrace();
	}

总结

  • 1、源转为字节数组
  • 2、资源不用手动释放,此时close()是个空方法
  • 3、一切对象都可以转为字节数组
  • 4、开辟的存储空间不宜过大
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值