Java总结IO篇之字节流与字符流转化

mac2022-06-30  114

本篇接上篇:Java中的字符流,流的读写的细节参考上篇 本篇讲述字节流相关话题,包括字节流的读取与写出,字节流转化为字符流 1.明确是否是纯文本:纯文本 ? 字符流: 字节流 2.明确数据来源( 输入流 I )和数据流向( 输出流 O ) 3.I流和O流对接,数据传输 另外:需要字符编码转换,使用字节流转换字符流

数据来源( 输入流 I ):内存、磁盘、网络、键盘 数据流向( 输出流 O ): 内存、磁盘、网络、控制台
1.最常见的几种流
最常见的几种流.png
2.流与流之间的相互作用:转换与包装
转换流和包装流.png

一、FileOutputStream与FileInputStream

1.FileOutputStream:输出流,写出操作
FileOutputStream fos = null; try { String fileName = "I:\\Java\\Base\\Thinking\\src\\IOTest\\FileInputStream.txt"; fos = new FileOutputStream(fileName); fos.write("Line1 第一行".getBytes());//不需要刷新缓冲 } catch (IOException e) { e.printStackTrace(); } finally { try { if (fos != null) { fos.close(); } } catch (IOException e) { e.printStackTrace(); } } 字节输出流.png
2.FileInputStream:输入流,读进操作
public static void main(String[] args) { try { String fileName = "I:\\Java\\Base\\Thinking\\src\\IOTest\\FileInputStream.txt"; FileInputStream fis = new FileInputStream(fileName); //readOneByOne(fis); //readByByteArrayByWhile(fis); } catch (IOException e) { e.printStackTrace(); } }
1)一个一个字节读
private static void readOneByOne(FileInputStream fis) throws IOException { int ch = 0; while ((ch = fis.read()) != -1) { System.out.println(ch + "=" + (char) ch); } }

一共输出了15个字节,和Line1 第一行有出入,原因: 在utf-8编码下,一个中文字符占三个字节

76=L 105=i 110=n 101=e 49=1 32= 231=ç 172=¬ 172=¬ 228=ä 184=¸ 128=� 232=è 161=¡ 140=�
2)字节数组方式:
private static void readByByteArrayByWhile(FileInputStream fis) throws IOException { //字符数组循环读取 byte[] buf = new byte[8]; int len = 0; while ((len = fis.read(buf)) != -1) { System.out.println(new String(buf, 0, len)); } }

可见buf一次装个字节,第由三个字节表示,被分成了两半,所以读出了乱码

//Line1 � //�一行 文件字节数 System.out.println(fis.available());//15

二、使用字节流拷贝

视频大小:576M

1.使用FileInputStream和FileInputStream拷贝

耗时:6.162444569秒

private static void copy() { FileOutputStream fos = null; FileInputStream fis = null; try { fis = new FileInputStream("I:\\Java\\Base\\Thinking\\src\\IOTest\\video.avi"); fos = new FileOutputStream("F:\\javaTest\\IO\\video.avi"); byte[] buf = new byte[1024]; int len = 0; while ((len = fis.read(buf)) != -1) { fos.write(buf, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (fis != null) { fis.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (fos != null) { fos.close(); } } catch (IOException e) { e.printStackTrace(); } }
2.使用包装类BufferedOutputStream和BufferedInputStream拷贝:

方法耗时:33.478968503秒

private static void copyByBuf() { BufferedOutputStream bfos = null; BufferedInputStream bfis = null; try { FileInputStream fis = new FileInputStream("I:\\Java\\Base\\Thinking\\src\\IOTest\\video.avi"); bfis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream("F:\\javaTest\\IO\\video.avi"); bfos = new BufferedOutputStream(fos); int b = 0; while ((b = bfis.read()) != -1) { bfos.write(b); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (bfis != null) { bfis.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (bfos != null) { bfos.close(); } } catch (IOException e) { e.printStackTrace(); } } }

三、字节流转化为字符流

场景一:将键盘录入写入到本地磁盘
分析:键盘录入是一个字节输入流: InputStream in = System.in; 由于输入的都是字符,使用字符流将比较方便(当然字节流也可以,不过麻烦一点) 1.用字符流InputStreamReader将字节流转化 2.再用字符包装流BufferedReader包装一下(当然也可以不包装,不过麻烦一点) 转换流和包装流.png public class Save2File { public static void main(String[] args) throws Exception { //数据源----键盘录入字节流转化为字符流后包装成BufferedReader BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入"; //数据流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入" 文件 BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path))); String line = null; while ((line=bfr.readLine())!=null){ if ("over".equals(line)) { break; } brw.write(line); brw.newLine(); brw.flush(); } bfr.close(); brw.close(); } } 键盘录入到文件.png
场景二:将键盘录入写入到本地磁盘:指定字符编码

默认字符编码为utf-8,这里使用GBK测试

public class Save2File { public static void main(String[] args) throws Exception { //数据源----键盘录入字节流转化为字符流后包装成BufferedReader BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入-GKB"; //数据流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入" 文件 BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path),"GBK")); String line = null; while ((line=bfr.readLine())!=null){ if ("over".equals(line)) { break; } brw.write(line); brw.newLine(); brw.flush(); } bfr.close(); brw.close(); } } GBK存储.png

可见两者的字节数不同,一个GBK的汉字占2个字节(2*5+\r\n=12) ,一个UTF-8汉字占3个字节(3*5+\r\n=17)

场景3:读取文件输出到控制台
分析:控制台输出是一个字节输出流:PrintStream out = System.out; 由于输出的都是字符,使用字符流将比较方便(当然字节流也可以,不过麻烦一点) 1.用字符流OutputStreamWriter将字节流转化 2.再用字符包装流BufferedWriter包装一下(当然也可以不包装,不过麻烦一点) public class ReadFile2Console { public static void main(String[] args) throws Exception { //数据源----本地文件 String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\Activity.md"; BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream(path))); //数据流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入" 文件 BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while ((line = bfr.readLine()) != null) { if ("over".equals(line)) { break; } brw.write(line); brw.newLine(); brw.flush(); } bfr.close(); brw.close(); } } 文件输出到控制台.png
场景4:改变系统流的流向

可以改变系统的录入流(数据来源),和控制台输出流(数据流向)

System.setIn(InputStream 输入流); 自定义System.in数据来源(默认键盘录入) System.setOut(PrintStream 输出流);自定义System.out数据流向(默认控制台) public class ReadFile2Console { public static void main(String[] args) throws Exception { //数据源----本地文件 String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\Activity.md"; System.setIn(new FileInputStream(path));//将键盘源改为了磁盘文件源 System.setOut(new PrintStream("F:\\hell.txt"));//将流向控制台改为流向磁盘文件 BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); //数据流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入" 文件 BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while ((line = bfr.readLine()) != null) { if ("over".equals(line)) { break; } brw.write(line); brw.newLine(); brw.flush(); } bfr.close(); brw.close(); } }

后记:捷文规范

1.本文成长记录及勘误表
项目源码日期备注V0.1--无2018-10-10Java中的字节流与字符流转化V0.2--无--
2.更多关于我
笔名QQ微信爱好张风捷特烈1981462002zdl1994328语言我的github我的简书我的个人网站
3.声明

1----本文由张风捷特烈原创,转载请注明 2----欢迎广大编程爱好者共同交流 3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正 4----看到这里,我在此感谢你的喜欢与支持

转载于:https://www.cnblogs.com/toly-top/p/9781849.html

最新回复(0)