文章目录

  • 1. 释放资源的方式
    • 1.1 try…catch…finally
      • 1.1.1 finally
        • 格式
        • 特点
        • 执行时机
      • 1.1.2 处理IO流中的异常
    • 1.2 try-with-resource
  • 2. 字节缓冲流
    • 2.1 概述
    • 2.2 字节缓冲流复制文件
      • 代码
      • 原理
    • 2.3 字节缓冲流+自定义数组赋值文件
      • 代码
      • 原理
  • 3. 字符集和编解码
    • 3.1 问题
    • 3.2 字符集
    • 3.3 String类中提供编码的方法
    • 3.4 解决字节流读中文乱码(了解)
  • 4. 文件字符流
    • 4.1 概述
    • 4.2 文件字符输入流
    • 4.3 文件字符输入流
    • 4.4 文件字符输出流注意事项
  • 5. 字符缓冲流
    • 5.1 概述
    • 5.2 字符缓冲输入流
    • 5.3 字符缓冲输出流
    • 5.4 练习
    • 5.5 扩展内容
  • 6. 转换流
    • 6.1 问题
    • 6.2 字符转换输入流
    • 6.3 字符转换输出流
  • 7. IO流小结

1. 释放资源的方式

1.1 try…catch…finally

1.1.1 finally

格式

try {// 有可能出现异常的代码
} catch(异常类名 变量名){// 成功捕获异常,执行的代码
} finally{// 不管是否出现异常,都会执行
}

特点

  • 不管是否有异常finally中的代码一定会执行
  • 以下情况除外
    • 在执行finally之前虚拟机停止了
    • 在执行finally之前程序阻塞了(比如死循环)
    • 在执行finally之前方法提前结束了(弹栈消失,多线程场景下)
public class Demo1 {/*try...catch...finally 处理异常的格式finally: 不论程序是否出现异常 都会执行finally中的代码在执行finally代码之前 虚拟机停止了在执行finally代码之前 程序阻塞(比如死循环)try{// 有可能出现异常的代码} catch(异常类名 变量名){// 如果捕获到异常,执行这里的代码} finally{//  不论程序是否出现异常 都会执行finally中的代码}*/public static void main(String[] args) {try {
//            System.out.println(1);System.out.println(1 / 0);
//            System.exit(0);} catch (Exception e) {System.out.println("出现异常了");} finally {System.out.println("finally...看看我执行了吗");}}
}

执行时机

  • 方法结束之前(return之前)执行
public class Demo2 {/*finally执行时机: 是在方法结束之前执行(return 之前)*/public static void main(String[] args) {String s = test();System.out.println(s);}public static String test(){try {System.out.println(1 / 0);return "正常执行了";} catch (Exception e){return "出现异常了"; // finally中的代码在return之前执行} finally {return "我是finally的代码";}}
}

1.1.2 处理IO流中的异常

  • 由于finally中的代码,不管是否出现异常一定会执行,可以将释放资源的代码放到finally中
public class Demo3 {/*finally处理io流中的释放资源(close方法)finally中的代码不管是否出现异常,都会执行fos.close(); 不管是否出现异常,都必须要释放资源把释放资源的代码写在finally中使用finally改写代码过程0.选中有可能出现异常的代码 Ctrl+Alt+T  选择 try/catch/finally1.fos.close()放到finally中   由于作用域的问题 fos是在try中定义的 finally中就无法使用2.提升作用域,在主方法中定义fos3.close()方法也有可能出现异常 ,也要使用try...catch包裹4.fos有可能是null 所以加非空验证,否则可能会出现空指针异常*/public static void main(String[] args) {FileOutputStream fos = null;try {fos = new FileOutputStream("day11-code\\01-finally.txt");fos.write(97);} catch (IOException e) {e.printStackTrace();} finally {if (fos != null){try {fos.close();} catch (IOException e) {e.printStackTrace();}}}}
}

1.2 try-with-resource

  • JDK7出现的语法
  • 前提: 只有实现了AutoCloseable接口的类才能使用该语法结构
  • 格式:
try(对象1;对象2;对象3;......){// 可能出现异常的代码
} catch(异常类名 变量名){
}
  • 好处: 不需要手动释放资源,自动释放资源(close方法自动执行)
public class Demo2 {public static void main(String[] args) {// 选中代码 Ctrl+ALt+T 选择使用try-with-resourcestry (FileOutputStream fos = new FileOutputStream("day18//finally.txt",true)) {fos.write(98);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

2. 字节缓冲流

2.1 概述

  • 字节缓冲输入流: BufferedInputStream

    • 自带默认大小8192(8KB)的数组
  • 字节缓冲输出流: BufferedOutputStream
    • 自带默认大小8192(8KB)的数组
  • 作用: 给其他字节流加速
  • 构造方法
构造方法 说明
public BufferedInputStream(InputStream is) 给其他字节输入流提高读数据的性能
public BufferedOutputStream(OutputStream os) 给其他字节输出流提高写数据的性能

2.2 字节缓冲流复制文件

代码

public class Demo1 {/*使用字节缓冲流操作文件的复制*/public static void main(String[] args) {// 从哪里读// 写到哪里去try (FileInputStream fis = new FileInputStream("day11-code\\file\\a.avi");BufferedInputStream bis = new BufferedInputStream(fis); // 给一个文件字节输入流加速FileOutputStream fos = new FileOutputStream("day11-code\\copy\\a.avi");BufferedOutputStream bos = new BufferedOutputStream(fos)// 给一个文件字节输出流加速) {// 循环读写 调用方法 使用缓冲流对象调用int b;while ((b = bis.read()) != -1){bos.write(b);}} catch (IOException e) {e.printStackTrace();}}
}

原理

  • 一次最多可以读8KB的字节到数组中
  • 一次最多写8KB的字节到文件中
  • 两个数组之间,一个字节一个字节的倒手
  • 减少了内存和硬盘交互的次数

2.3 字节缓冲流+自定义数组赋值文件

代码

public class Demo2 {/*字节缓冲流+自定义的数组 实现文件的复制*/public static void main(String[] args) {try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day11-code\\file\\a.avi"));BufferedOutputStream  bos = new BufferedOutputStream(new FileOutputStream("day11-code\\copy\\a.avi"))) {// 定义一个字节数组byte[] bytes = new byte[1024];int len; // 记录的是字节的个数while ((len = bis.read(bytes)) != -1){bos.write(bytes,0,len);}} catch (IOException e) {e.printStackTrace();}}
}

原理

3. 字符集和编解码

3.1 问题

  • 字节流读取中文会出现乱码
public class Demo3 {public static void main(String[] args) {//abc ASCII码表//中try (FileInputStream fis = new FileInputStream("day18\\test.txt")) {int b;while ((b = fis.read()) != -1){System.out.print((char) b);}} catch (IOException e) {e.printStackTrace();}}
}

3.2 字符集

  • ASCII字符集: 由符号,数字,字母 占用1个字节

  • GBK字符集(中国人发明的): 中文占2个字节,兼容ASCII 占1个字节

    • windows系统中ANSI实际使用的就是GBK字符集
  • UTF-8字符集(Unicode码表,万国码): 中文占3个字节,兼容ASCII 占1个字节

  • 实际开发中最常用的UTF-8

  • 字节流读中文出现乱码的原因? 读中文,每次只能读一部分

3.3 String类中提供编码的方法

  • 编码: 按指定的字符集将字符串编码成字节
  • 解码: 按指定的字符集将字节解码成字符串
String提供编码方法 说明
public byte[] getBytes() 使用平台(idea)默认的字符集编码
public byte[] getBytes(String charsetName) 使用指定名称的字符集编码
String提供解码方法 说明
public String(byte[] bytes) 使用平台(idea)默认的字符集解码
public String(byte bytes[], String charsetName) 使用指定名称的字符集解码
public class Demo4 {public static void main(String[] args) throws UnsupportedEncodingException {//String 提供的编码方法System.out.println("----------String 提供的编码方法----------");String s1 = "a1你好";byte[] bytes1 = s1.getBytes();//使用平台(idea)默认的字符集编码  UTF-8 中文占3个字节System.out.println(Arrays.toString(bytes1));byte[] bytes2 = s1.getBytes("gbk");//使用指定字符集编码  GBK 中文占2个字节System.out.println(Arrays.toString(bytes2));System.out.println("----------String 提供的解码方法----------");String UTFStr = new String(bytes1);System.out.println(UTFStr);String GBKStr = new String(bytes2,"gbk");System.out.println(GBKStr);}
}

3.4 解决字节流读中文乱码(了解)

/*使用字节流读中文,手动将字节指定字符集,将字节转成字符串1.先读到一个字节数组中,int read(byte[] b)2.得到一个字节数组,new String(字节数组)指定字符集将字节转成字符串
*/
public class Demo4 {public static void main(String[] args) {final File file = new File("day18//test.txt");try (FileInputStream fis = new FileInputStream(file)){// 定义一个字节数组,文件有多少字节,创建多大的数组byte[] bytes = new byte[(int) file.length()];int len;while ((len = fis.read(bytes)) != -1){String s = new String(bytes,"gbk");System.out.println(s);}} catch (IOException e) {e.printStackTrace();}}
}

4. 文件字符流

4.1 概述

既然字节流可以操作所有类型的文件, 为什么还要学习字符流呢?

  • 字节流: 用于文件的复制

    • 字节流读中文会出现乱码
  • 字符流: 读写文本文件中的数据

4.2 文件字符输入流

  • FileReader
构造方法 说明
public FileReader(File file) 创建字符输入流管道与源文件接通
public FileReader(String pathname) 创建字符输入流管道与源文件接通
读方法 说明
public int read() 每次读取一个字符返回,如果发现没有数据可读会返回-1.
public int read(char[] buffer) 每次用一个字符数组去读取数据,返回字符数组读取了多少个字符,如果发现没有数据可读会返回-1.
public class Demo1 {/*文件字符输入流读取带有中文的文本文件FileReader*/public static void main(String[] args) throws IOException {FileReader fr = new FileReader("day11-code\\中文.txt");int b;while ((b = fr.read()) != -1){System.out.print((char) b);}fr.close();}
}

4.3 文件字符输入流

  • FileWriter
构造方法 说明
public FileWriter(File file) 创建字符输出流管道与源文件对象接通
public FileWriter(String filepath) 创建字符输出流管道与源文件路径接通
public FileWriter(File file,boolean append) 创建字符输出流管道与源文件对象接通,可追加数据
public FileWriter(String filepath,boolean append) 创建字符出流管道与源文件路径接通,可追加数据
写方法 说明
void write(int c) 写一个字符
void write(String str) 写一个字符串
void write(String str, int off, int len) 写一个字符串的一部分
void write(char[] cbuf) 写入一个字符数组
void write(char[] cbuf, int off, int len) 写入字符数组的一部分
public class Demo2 {/*文件字符输出流FileWriter*/public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("day11-code\\中文.txt",true);
//        fw.write(97); // a
//        fw.write("你好"); // 你好
//        fw.write("好好学习天天向上",2,3);char[] chars = {'学','I','T','就','来','黑','马'};
//        fw.write(chars);fw.write(chars,1,2);fw.close();}
}

4.4 文件字符输出流注意事项

  • 输出流写数据之后,必须刷新流,或者关闭流,写出去的数据才能生效
方法名 说明
public void flush() throws IOException 刷新流,就是将内存中缓存的数据立即写到文件中去生效!
public void close() throws IOException 关闭流的操作,包含了刷新!

5. 字符缓冲流

5.1 概述

5.2 字符缓冲输入流

  • BufferedReader
  • 自带默认8192(8KB)字符数组
构造方法 说明
public BufferedReader(Reader r) 给其他字符输入流提高读数据的性能
特有的读方法 说明
public String readLine() 读取一行数据返回,如果没有数据可读了,会返回null
public class Demo1 {public static void main(String[] args) {try (BufferedReader br = new BufferedReader(new FileReader("day18\\finally.txt"));){String line;while ((line = br.readLine()) != null){System.out.println(line);}} catch (IOException e) {e.printStackTrace();}}
}

5.3 字符缓冲输出流

  • BufferedWriter
  • 自带默认8192(8KB)字符数组
构造方法 说明
public BufferedWriter(Writer r) 给其他字符输入流提高写数据的性能
特有的写方法 说明
public void newLine() 换行
/*字符缓冲输入流使用:BufferedWriter*/
public class Demo2 {public static void main(String[] args) {try (BufferedWriter bw = new BufferedWriter(new FileWriter("day18//finally.txt",true));){bw.newLine();bw.write("风吹过八千里,");bw.newLine();bw.write("流云和月都曾爱过你!");bw.newLine();bw.flush();//可以将数据真正的写出去} catch (IOException e) {e.printStackTrace();}}
}

5.4 练习

  • 需求: 读取文件中的数据,排序后再次写到本地,同一文件
  • 文件中的数据: 9 1 2 5 3 10 4 6 7 8
/*- 需求: 读取文件day18//test_char.txt中的数据,排序后再次写到本地,同一文件- 文件中的数据: 9 1 2 5 3 10 4 6 7 8分析:1.读 使用字衬绒冲输入流BufferedReader   String readLine()"9 1 2 5 3 10 4 6 7 8"2.字符串切制 使用空格 string[] {"9","1","2","5","3" ,"10","4" ,"6","7” ,"8"}3.遍历字符中数姐 把每一个字符中 转换成1nt类型,存入到int数组中4.排序5.遍历数组 写国到文件中*/
public class Demo {public static void main(String[] args) {BufferedReader br = null;BufferedWriter bw = null;try{//1.BufferedReader读取数据br = new BufferedReader(new FileReader("day18//test_char.txt"));//FiLeWriter构造方法如果文件存在,会清空数据,不能连着写,否则line读取不到数据会为null//bw = new BufferedWriter(new FileWriter("day18//test_char.txt"));String line = br.readLine();//2.使用空格切割字符串String[] str = line.split(" ");//3.把字符串数组转成int数组int[] arr = new int[str.length];for (int i = 0; i < str.length; i++) {arr[i] = Integer.parseInt(str[i]);}//4.排序Arrays.sort(arr);//5.遍历int数组 拼接成读取到的字符串模式StringJoiner sj = new StringJoiner(" ");for (int i : arr) {sj.add(String.valueOf(i));}System.out.println(sj);//6.存入数据bw = new BufferedWriter(new FileWriter("day18//test_char.txt"));bw.write(sj.toString());bw.flush();} catch (IOException e) {e.printStackTrace();}finally {try {assert br != null;br.close();assert bw != null;bw.close();} catch (IOException e) {e.printStackTrace();}}}
}

5.5 扩展内容

BufferedReader中的方法 说明
public Stream lines() 读取文件中每一行数据,将每一行的数据放到Stream中返回
Stream中的方法 说明
Stream flatMap(s -> Stream流) 把Stream中的每一个元素生成一个新的Stream,并合并生成的每一个Stream
collect(Collectors.joining(“分隔符”)) 当Stream中的元素都是字符串时,可以按照指定的分隔符拼接Stream中的字符串
  • 方法使用

Stream.txt

a,b,c,d
e,f,g,h
i,j
public class Demo3 {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new FileReader("day11-code\\Stream.txt"));String s1 = br.lines().flatMap(s -> Arrays.stream(s.split(","))) // a,b,c,d,e,f,g,h,i,j.collect(Collectors.joining("-"));// "a-b-c-d-e-f-g-h-i-j"System.out.println(s1);br.close();}
}
//练习简洁写法
public class Demo3 {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new FileReader("day18\\test_char.txt"));final String result = br.lines()//读取一行字符串,把这个字符串放到Stream.flatMap(s -> Arrays.stream(s.split(" "))).map(Integer::parseInt)//把字符串转换成int  s -> Integer.parseInt(s).sorted()//排序.map(String::valueOf)//int转换为String,joining 要求Stream中的元素必须是字符串  s -> String.valueOf(s).collect(Collectors.joining(" "));System.out.println(result);br.close();bw = new BufferedWriter(new FileWriter("day18//test_char.txt"));bw.write(result);bw.flush();bw.close();}
}

6. 转换流

6.1 问题

  • 问题: 字符流读中文也有可能出现乱码
  • 原因:
    • 如果代码编码和被读取的文本文件的编码是一致的,使用字符流读取文本文件时不会出现乱码!
    • 如果代码编码和被读取的文本文件的编码是不一致的,使用字符流读取文本文件时就会出现乱码!
public class Demo1 {public static void main(String[] args) throws IOException {//文件GBK编码  一个中文2个字节//idea默认解码UTF-8  一个中文3个字节FileReader fr = new FileReader("day18\\test.txt");int b;while ((b = fr.read()) != -1){System.out.println((char) b);}}
}
  • 解决办法:使用转换流指定字符集(编/解码格式)读写

6.2 字符转换输入流

  • InputStreamReader
构造方法 说明
public InputStreamReader(InputStream is) 把字节输入流,按照代码默认编码转成字符输入流(与直接用FileReader的效果一样)
public InputStreamReader(InputStream is ,String charset) 把字节输入流,按照指定字符集编码转成字符输入流(重点)
public class Demo2 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("day18\\test.txt");InputStreamReader isr = new InputStreamReader(fis,"gbk");//给fis文件字节输入流读出来的字节,指定了GBK的字符集,做解码int b;while ((b = isr.read()) != -1){System.out.print((char) b);}isr.close();}
}

6.3 字符转换输出流

  • OutputStreamWriter
构造方法 说明
public OutputStreamWriter(OutputStream os) 可以把字节输出流,按照代码默认编码转换成字符输出流。
public OutputStreamWriter(OutputStream os,String charset) 可以把字节输出流,按照指定编码转换成字符输出流(重点)
public class Demo3 {/*字符转换输出流: OutputStreamWriter*/public static void main(String[] args) throws IOException {OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11-code\\GBK.txt"),"GBK");osw.write("好好学习天天向上");osw.flush();osw.close();}
}

7. IO流小结

【学习日记2023.4.9】之释放资源的方式_编解码_字符流(Reader/Writer)及其子类_转换流( [In/Out]putStreamReader)相关推荐

  1. 【学习日记2023.4.25】之 前后端分离_前端工程化_Vue组件库Element_Vue路由_打包部署

    文章目录 1. 前后台分离开发 1.1 前后台分离开发介绍 1.2 YAPI 1.2.1 YAPI介绍 1.2.2 接口文档管理 2. 前端工程化 2.1 前端工程化介绍 2.2 前端工程化入门 2. ...

  2. 【学习日记2023.5.8】之 springboot案例之登录功能(会话技术_JWT令牌_过滤器_拦截器)

    文章目录 1. 案例-登录认证 1. 1登录功能 1.1.1 需求 1.1.2 接口文档 1.1.3 思路分析 1.1.4 功能开发 1.1.5 测试 1.1.6 全后端联调 1.2 登录校验 1.2 ...

  3. 【学习日记2023.6.9】之 SpringCloud入门(认识微服务_服务拆分和远程调用RestTemplate_Eureka注册中心_Ribbon负载均衡_Nacos注册中心)

    文章目录 SpringCloud 1. 认识微服务 1.1 单体架构 1.2 分布式架构 1.3 微服务 1.4 SpringCloud 1.5 总结 2. 服务拆分和远程调用 2.1 服务拆分原则 ...

  4. 菜鸟学习笔记:Java提升篇5(IO流1——IO流的概念、字节流、字符流、缓冲流、转换流)

    菜鸟学习笔记:Java IO流1--IO流的概念.字节流.字符流.缓冲流.转换流 IO流的原理及概念 节点流 字节流 文件读取 文件写出 文件拷贝 文件夹拷贝 字符流 文件读取 文件写出 处理流 缓冲 ...

  5. 【FFMPEG】各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式

    目录(?)[-] 编解码学习笔记二codec类型 编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2 编解码学习笔记四Mpeg系列Mpeg 4 编解码学习笔记五Mpeg系列AAC音频 编解码学习笔 ...

  6. 音视频编解码学习详解

    音视频编解码学习详解 目录(?)[+] 编解码学习笔记二codec类型 编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2 编解码学习笔记四Mpeg系列Mpeg 4 编解码学习笔记五Mpeg系列A ...

  7. (学习日记)2023.06.07

    写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈. 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈. 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录, ...

  8. (学习日记)2023.04.28

    写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈. 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈. 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录, ...

  9. (学习日记)2023.04.25

    写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈. 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈. 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录, ...

最新文章

  1. Spring整合Hibernate的步骤
  2. Django博客系统(发表评论)
  3. 【深度学习】图片分类CNN模板
  4. SpringBoot 中 @RequestBody的正确使用方法
  5. 终于可以放下心来了,呜呜...
  6. 在Linux和Mac OS X系统上运行.NET
  7. linux命令栏下访问oracle,linux下远程连接oracle数据库
  8. KafkaConsumer分析
  9. 计算机专业行业分析300字,计算机专业毕业生自我鉴定范文300字(精选5篇)
  10. JQuery中$.ajax()方法参数详解 转载
  11. 计算机地址输入法教案,计算机教案(输入法
  12. 用hyperf框架开发JsonRpc服务
  13. 感性电路电流计算_220和380V功率和电流计算知识。
  14. Tungsten Replicator
  15. 计算机切换到桌面,电脑桌面切换软件 电脑桌面快速切换
  16. 水晶易表 Xcelsius 2008 安装指南学习资源
  17. C# Winform Socket即时通讯
  18. Understanding the Users and Videos by Mining a Novel Danmu Dataset
  19. 【安全硬件】Chap.6 IC和半导体产业的全球化;芯片生产猜疑链与SoC设计流程;可能会存在的安全威胁: 硬件木马、IP盗版、逆向工程、侧信道攻击、伪造
  20. 【bzoj4372】 烁烁的游戏【动态树分治】

热门文章

  1. python爬取文章保存为txt_爬取博主所有文章并保存到本地(.txt版)--python3.6
  2. 百度地图API显示多个标注点带提示的代码 / 单个标注点带提示代码
  3. 图像融合质量评价方法MSSIM、MS-SSIM、FS、Qmi、Qabf与VIFF(三)
  4. 多线程与多进程(转)
  5. android 手电筒的实现
  6. AIGC学习,AI绘画、AI写作、国内外研究现状等
  7. CKA备考实验 | 汇总
  8. android view flipper,Android之ViewFlipper的简单使用
  9. pcb - 家用桌面型回流焊机不能买功率太大的
  10. 历代小米黑鲨手机主要参数对比,更新于2021年3月