• 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----看到这里,我在此感谢你的喜欢与支持

  • 相关阅读:
    POST GET原理函数
    位宽与带宽
    编程小工具
    C#的四个基本技巧
    关闭弹出模态窗口以后刷新父窗口
    十年技术,不要再迷茫
    冒泡排序
    单元测试工具及资源推荐
    xml xhtml html dhtml的区别
    删除List<string>中重复的值
  • 原文地址:https://www.cnblogs.com/toly-top/p/9781849.html
Copyright © 2020-2023  润新知