详解OutputStream和InputStream Reader和Writer InputStreamReader

  1. OutputStream和InputStream
    字节输入和输出流,有字节文件流,字节对象流。ObjectOutputStream是对象序列化用的。FileInputStream/FileOutputStream用来读写文件。

  2. Reader和Writer
    字符流,字节流中包含FileRead,InputStreamReader和BufferedReader。最重要的类是InputStreamReader,它是字节转换为字符的桥梁,这里就用到了适配器模式。关于适配器模式看我其他的博客。java默认的编码方式是Unicode,在字符流中默认的编码方式是GBK,在创建InputStreamReader对象的时候可以指定编码的方式。

  3. 字节流和字符流的区别
    字节流读取二进制文件,字符流读取文本文件。
    实际上字符流是这样工作的:
    输出字符流:把要写入文件的字符序列(实际上是Unicode码元序列)转为指定编码方式下的字节序列,然后再写入到文件中;
    输入字符流:把要读取的字节序列按指定编码方式解码为相应字符序列(实际上是Unicode码元序列从)从而可以存在内存中。
    所以字符流是自带缓存功能的。

字节流不带缓存功能,如果要缓存得用BufferedInputStream。即使是FileInputStream中read()方法,传入byte[]数组参数,它在源代码中也是循环从电脑中一个一个读取。
所以字节流无形中增加了磁盘IO。
这里写图片描述

字节流读取写入代码

public class Solution {
    public static void main(String[] args){
        //Out();
        In();
    }
    private static void Out(){
        //0确定目标文件
        File file = new File("D:/test.txt");
        try {
            OutputStream out = new FileOutputStream(file, true);
            String info = "小河流水测试河流";
            try {
                out.write(info.getBytes());
                out.close();
                System.out.println("write success");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private static void In(){
        File file = new File("D:/test.txt");
        try {
            InputStream in = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(in,"UTF-8");
            byte[] bytes = new byte[6];
            StringBuilder buf = new StringBuilder();
            int len = -1;
            try {
                while ((len = in.read(bytes)) != -1){
                    buf.append(new String(bytes));
                }
                in.close();
                System.out.println("输出打印内容");
                System.out.println(buf);
            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

}

这里如果写入txt文件的是纯字母的话没有问题,因为一个英文字母是一个字节,用byte[]

刚刚碰到一个问题:java中char占用2个字节,值范围是0-65535,byte是1个字节,值范围是-128-127。在InputStream实现类中有方法read(),字符串中如果没有参数是用read()的返回的是char类型的字符对应的数值,然后我们用char强制转换,这里返回的结果不会是-1。所以我们可以用-1来判断是否读取到最后一位了。但是在字节流中,我们返回的值是-128到127的范围,那-1是涵盖在里面的,如果得到了-1,如何判断是结束呢还是我得到的就是-1。
经过查资料,我发现,在字节流读取中,得到的字符会将高位的1转化为0,转到字节的时候再用byte强制转换回来。
http://blog.csdn.net/daijunjian/article/details/7316275可以参考这篇博客

第二个问题:在字节流中写入的是字节,英文和数字对应的就是单字节。但是在java中这些表示自然语言肯定不够,所以会有其他编码集。但是在字节流中,不管输入的是什么就是当做二进制文件的。
https://www.cnblogs.com/haojun/p/7759955.html可以参考这篇博客

字符流

public class Solution {
    public static void main(String[] args){
        //Out();
        In();

    }

    private static void In(){
        File file = new File("D:/test.txt");
        try {
            Reader in = new FileReader(file);
            char[] cs = new char[1];
            int len = -1;
            StringBuilder buf = new StringBuilder();
            try {
                while ((len = in.read(cs)) != -1){
                buf.append(new String(cs));
                }
                in.close();
                System.out.println("读入成功");
                System.out.println(buf);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }
    private static void Out(){
        File file = new File("D:/test.txt");
        try {
            Writer out = new FileWriter(file);
            out.write("村花到我家");
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

适配器,InputStreamReader
在字节流的代码中,如果写入的是汉子,用字节流的话,很容易乱码。这是可以把字节流转换为字符流来读取。然后指定编码方式,默认的是GBK。

这就是字节流,每个数字都是一个字节(Byte,8位),所以如果读取英文的话,用字节流,然后用(char)强制转化一下就行了,但如果有中文等双字节语言或者说需要指定字符编码集的情况,就必须用到InputStreamReader将字节流转化为字符流了。
http://blog.csdn.net/zgljl2012/article/details/47267609这个可以参考这篇博客,这篇博客举了URL获取网页字节流的例子。

public class Solution {
    public static void main(String[] args){
        Out();
        In();
    }
    private static void Out(){
        //0确定目标文件
        File file = new File("D:/test.txt");
        try {
            OutputStream out = new FileOutputStream(file, true);
            String info = "小河流水测试河流";
            try {
                out.write(info.getBytes());
                out.close();
                System.out.println("write success");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private static void In(){
        File file = new File("D:/test.txt");
        try {
            InputStream in = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(in,"UTF-8"); //字节流转字符流 用到了适配器模式。
            byte[] bytes = new byte[6];
            char[] chars = new char[1];
            StringBuilder buf = new StringBuilder();
            int len = -1;
            try {
                while ((len = isr.read(chars)) != -1){
                    //buf.append(new String(bytes));
                    buf.append(chars);
                }
                in.close();
                System.out.println("输出打印内容");
                System.out.println(buf);
            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值