目录
3.使用try - catch - finally 优化资源释放
前言
大多数应用程序都需要实现与设备之间的数据传输,例如键盘可以输入数据,显示器可以显示程序的运行结果等。在Java中,将这种通过不同输入输出设备(键盘,内存,显示器,网络等)之间的数据传输抽象的表述为“流”,程序允许通过流的方式与输入输出设备进行数据传输。Java中的“流”都位于Java.io包中,称之为IO(输入输出)流。 IO流:即InputOutput的缩写。
一、了解IO流
1.IO流的特点
IO流用来处理设备间的数据传输。
Java对数据的操作是通过流的方式。
Java用于操作流的对象都在IO包中。
流按操作数据分为两种:字节流和字符流。
流按流向分为:输入流和输出流
2.流的三种分类方式
按流的方向分为:输入流和输出流
按流的数据单位不同分为:字节流和字符流
按流的功能不同分为:节点流和处理流
3.流的层次结构
IO流的常用基类:
- 字节流的抽象基流:InputStream和OutputStream
- 字符流的抽象基流:Reader和Writer
二、字节流
1.什么是字节流
一切文件数据在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。
2.使用字节流实现文件拷贝
无论是音视频文件还是文本文件底层都是字节组成,因此可以使用字节输入流&字节输出流完成任何形式文件拷贝(只要保证前后文件格式、编码一致没有任何问题)
注意: 字节流不适合读取中文内容输出,(在UTF-8编码中,一个中文字符是3个字节)容易出现截断导致乱码
public static void main(String[] args) { try { //创建字节输入流管道 InputStream is = new FileInputStream("E:\\Pictures\\wx_camera_1654694320902.mp4"); //创建字节输入流管道 OutputStream os = new FileOutputStream("C:\\Users\\小茵\\Desktop\\lhy.mp4"); //定义一个1024大小字节数组,用来转移数据 byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ os.write(buffer,0,len); } System.out.println("复制完成!~~~~~"); //关闭流 os.close(); is.close(); } catch (Exception e) { e.printStackTrace(); } }
3.使用try - catch - finally 优化资源释放
finall代码块是最终一定会执行的,可以在在这里完成最后释放资源
public static void main(String[] args) { InputStream is = null; OutputStream os = null; try { //创建字节输入流管道 is = new FileInputStream("E:\\Pictures\\wx_camera_1654694320902.mp4"); //创建字节输入流管道 os = new FileOutputStream("C:\\Users\\小茵\\Desktop\\lhy.mp4"); //定义一个1024大小字节数组,用来转移数据 byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ os.write(buffer,0,len); } System.out.println("复制完成!~~~~~"); } catch (Exception e) { e.printStackTrace(); }finally { //无论代码正常结束还是出现异常都要执行这里 try { //先判断非空,然后关闭流 if (os != null)os.close(); } catch (IOException e) { throw new RuntimeException(e); } try { if (is != null)is.close(); } catch (IOException e) { throw new RuntimeException(e); } } }
4.使用try - catch - resource 进一步优化资源释放
public static void main(String[] args) { try ( //此处只能放置资源对象,使用完毕后即使出现异常也会自动调用资源对象的close方法关闭资源 //创建字节输入流管道 InputStream is = new FileInputStream("E:\\Pictures\\wx_camera_1654694320902.mp4"); //创建字节输入流管道 OutputStream os = new FileOutputStream("C:\\Users\\小茵\\Desktop\\lhy.mp4"); ){ //定义一个1024大小字节数组,用来转移数据 byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ os.write(buffer,0,len); } System.out.println("复制完成!~~~~~"); } catch (Exception e) { e.printStackTrace(); } }
三、字符流
1.什么是字符流
由于字节流读取中文有可能会应截断导致乱码,所以,java就提供了转换流。字符流=字节流+编码表。
编码表:由字符及其对应的数值组成的一张表
2.文件字符输入流 - 每次读取单个字符
读取中文字符不会出现乱码
但性能较慢
public static void main(String[] args) throws IOException { Reader fr = new FileReader("D:\\IDEA\\untitled1\\练习草稿\\Test1\\src\\data.txt"); int code; while ((code = fr.read()) != -1){ System.out.print((char) code); } }
3. 文件字符输入流 - 每次读取一个字符数组
性能相对于读取单个字符得到了提升
public static void main(String[] args) throws IOException { Reader fr = new FileReader("D:\\IDEA\\untitled1\\练习草稿\\Test1\\src\\data.txt"); char[] buffer = new char[1024]; int len; while ((len = fr.read(buffer)) != -1){ String rs = new String(buffer,0,len); System.out.print(rs); } }
4.字符输出流
public static void main(String[] args) throws IOException { //创建字符输出流管道与目标文件接通 Writer fw = new FileWriter("D:\\IDEA\\untitled1\\练习草稿\\Test1\\src\\data.txt"); //写一个字符出去 fw.write(1); fw.write('a'); fw.write('哈'); //写一个字符串出去 fw.write("哈哈哈哈哈"); //写一个字符数组出去 char[] chars = "abcdef".toCharArray(); fw.write(chars); //只写一部分字符数组、字符串 fw.write(chars,0,3); fw.write("哈哈哈哈哈",0,3); //关闭 fw.close(); }
总结
- 字节流适合做一切文件数据拷贝
- 字节流不适合读取中文内容输出
- 字符流适合做文本文件的操作(读、写)