zoukankan      html  css  js  c++  java
  • Java总结IO篇之字节流与字符流转化

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

    数据来源( 输入流 I ):内存、磁盘、网络、键盘    
    数据流向( 输出流 O ): 内存、磁盘、网络、控制台    
    
    1.最常见的几种流
    9414344-51ddbaea0edd3a1d.png
    最常见的几种流.png
    2.流与流之间的相互作用:转换与包装
    9414344-1bae611af7db90b2.png
    转换流和包装流.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();
         }
     }
    
    9414344-489cac370aad7f6d.png
    字节输出流.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包装一下(当然也可以不包装,不过麻烦一点)
    
    9414344-1bae611af7db90b2.png
    转换流和包装流.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();
        }
    }
    
    9414344-b0dfa3726a76811e.png
    键盘录入到文件.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();
        }
    }
    
    9414344-4c519228680a3a3e.png
    GBK存储.png

    可见两者的字节数不同,一个GBK的汉字占2个字节(2*5+ =12) ,一个UTF-8汉字占3个字节(3*5+ =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();
        }
    }
    
    9414344-e9614229e272ca27.png
    文件输出到控制台.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-10 Java中的字节流与字符流转化
    V0.2--无 - -
    2.更多关于我
    笔名 QQ 微信 爱好
    张风捷特烈 1981462002 zdl1994328 语言
    我的github 我的简书 我的CSDN 个人网站
    3.声明

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

  • 相关阅读:
    Linnia学习记录
    漫漫考研路
    ENS的学习记录
    KnockoutJS 3.X API 第四章 数据绑定(4) 控制流with绑定
    KnockoutJS 3.X API 第四章 数据绑定(3) 控制流if绑定和ifnot绑定
    KnockoutJS 3.X API 第四章 数据绑定(2) 控制流foreach绑定
    KnockoutJS 3.X API 第四章 数据绑定(1) 文本及样式绑定
    KnockoutJS 3.X API 第三章 计算监控属性(5) 参考手册
    KnockoutJS 3.X API 第三章 计算监控属性(4)Pure computed observables
    KnockoutJS 3.X API 第三章 计算监控属性(3) KO如何实现依赖追踪
  • 原文地址:https://www.cnblogs.com/toly-top/p/9781849.html
Copyright © 2011-2022 走看看