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

本篇接上篇: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-10

Java中的字节流与字符流转化

V0.2--无

-

-

2.更多关于我

笔名

QQ

微信

爱好

张风捷特烈

1981462002

zdl1994328

语言

我的github

我的简书

我的CSDN

个人网站

3.声明

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android开发指南

14:IO之字符字节流

3649
来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-20(02)总结,递归,IO流

(4)FileInputStream读取数据 A:操作步骤 a:创建字节输入流对象 b:调用read()方法 c:释放资源 B:代码体现: File...

3556
来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-21(01)总结字符流,IO流编码问题,实用案例必做一遍

1:字符流(掌握) // 字节流读取中文可能出现的小问题(所以用字符流输入输出中文) package cn.itcast_01; import java.io...

3364
来自专栏钟绍威的专栏

初识字节流+实现缓冲字节流OutputStream的主要方法构造方法读关流实现BufferedInputStream实现BufferedOutputStream为什么read()返回的是Int型而不是

java中的IO流可以分为两种:字符流和字节流 字符流,顾名思义,就是对字符进行操作,只能操作文本文件 字节流,就是对字节进行操作,然而所有文件都是由字...

1948
来自专栏spring源码深度学习

java基础io流——OutputStream和InputStream的故事(温故知新)

IO流用来处理设备之间的数据传输,上传文件和下载文件,Java对数据的操作是通过流的方式,Java用于操作流的对象都在IO包中。

1332
来自专栏xingoo, 一个梦想做发明家的程序员

【java开发系列】—— java输入输出流

前言   任何语言输入输出流都是很重要的部分,比如从一个文件读入内容,进行分析,或者输出到另一个文件等等,都需要文件流的操作。这里简单介绍下reader,w...

2447
来自专栏JAVA技术站

JAVA IO流之BufferedInputStream,BufferedOutputStream

BufferedInputStream的数据成员buf是一个位数组,默认为2048字节。当读取数据来源时,例如文件,BufferedInputStream会尽量...

872
来自专栏老付的网络博客

java中的字符和流

在计算机中,我们知道,所有的一切都是归根到底都是二进制的字节形式,包括文件,字符串等等。所以在写程序的时候,尝尝需要和字节打交道。

832
来自专栏钟绍威的专栏

简单的Writer和ReaderWriter的主要方法Writer工作原理Reader的主要方法readLine():String

Writer用于写出去到文件中,Reader用于将外面的文件读进来控制台 Writer和Reader有许多子类,但是子类大多都是直接运用父类Writer和R...

2005
来自专栏海纳周报

修饰者模式

java.io 这个包里有一个类,比较特别,这就是BufferedReader。我们从JDK的源码里,找到它的实现: public class Buffered...

36112

扫码关注云+社区

领取腾讯云代金券