记一次java的System类setOut方法改变输出流向失效问题的解决方法

4 篇文章 0 订阅

博主学了打印流PrintStream后做了个小练习,功能就是往文件b.txt中打印一个字符串,并且利用System类的setOut方法改变标准输出流的流向,将另一个文件a.txt里的内容读取出来打印到控制台显示,,下面上代码↓

/*
    将a.txt打印到控制台,同时往文件中打印一句字符串
     */
    public static void printStreamDemo() throws IOException {
        //创建字节缓冲输入流读取文件内容到内存
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
        //定义字节数组作为缓冲区接收每次读取到的有效字节,提高读取效率
        byte[] bytes = new byte[1024];
        //初始化一个变量len接收每次读取到的有效字节个数
        int len = 0;
        //声明一个打印流,避免变量作用域导致无法关流的问题
        PrintStream ps = null;
        //读取文件数据
        while ((len = bis.read(bytes)) != -1) {
            //构造一个带自动刷新的打印流,打印到文件
            ps = new PrintStream(new FileOutputStream("b.txt"), true);
            //使输出流的流向为文件
            System.setOut(ps);
            //打印一句话到文件,且不换行
            System.out.print("这句话是输出到b.txt文件的");
            //构造一个带自动刷新的打印流,打印到控制台
            ps = new PrintStream(System.out, true)
            //改变输出的流向为控制台,开启自动刷新
            System.setOut(ps);
            //将读取到的有效字节打印到控制台,且不换行
            System.out.print(new String(bytes, 0, len));
        }
        //释放资源
        if(ps!=null){
            ps.close();
        }
        bis.close();
    }

a.txt里面有一段文字↓

这段文字怎么看起来这么熟悉?没错,就是杰伦的发如雪(手动滑稽),而b.txt则是一个空文本。

然而程序的执行结果如下:

是的,你没有看错,控制台什么都没有显示,很显然输出流的流向并没与被改变成打印到控制台,那么控制台没有的话那个字符串打印到哪儿去了呢?我们把打印的目的地文件b.txt打开看一下↓

对于这个问题,博主尝试了很多种方法去排错,用debug一行行走也没找出问题,也看了setOut的源码,但是终究没能弄明白其中的原因,但是博主尝试把PrintStream定义到外面时,里面setOut方法直接传入后,运行发现这回正确了↓

    /*
        将a.txt打印到控制台,同时往文件中打印一句字符串
     */
    public static void printStreamDemo() throws IOException {
        //创建字节缓冲输入流读取文件内容到内存
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
        //定义字节数组作为缓冲区接收每次读取到的有效字节,提高读取效率
        byte[] bytes = new byte[1024];
        //定义len接收每次读取到的有效字节个数
        int len = 0;
        //创建带自动刷新的打印流,打印到文件
        PrintStream ps = new PrintStream(new FileOutputStream("b.txt"), true);
        //创建带自动刷新的打印流,打印到控制台
        PrintStream out = new PrintStream(System.out, true);
        //读取文件数据
        while ((len = bis.read(bytes)) != -1) {
            //使输出的内容的目的地为文件
            System.setOut(ps);
            //打印一句话到文件,且不换行
            System.out.print("这句话是输出到b.txt文件的");
            //使输出的内容的目的地为控制台
            System.setOut(out);
            //将读取到的有效字节打印到控制台
            System.out.print(new String(bytes, 0, len));
        }
        //释放资源
        ps.close();
        bis.close();
    }

运行结果↓

原因:

之前没有打印到控制台的原因是因为博主使用ps=new PrintStream(System.out,true)时,里面的参数System.out仍然获取到的是文件的输出流向,因为在这行执行之前当前输出流就已经被setOut为输出到文件了,所以第二次setOut(ps)并没有改变任何输出的流向,仍然往文件中打印,那么为什么将其定义在外面就可以了呢?因为在循环外时我们还没有将输出流的流向setOut为输出到文件,所以PrintStream out = new PrintStream(System.out,true)中的System.out获取的是默认的打印打控制台的流向,然后分别设置到两个打印流的setOut流向,这样才解决了这个问题。

总结:

System.out是默认往控制台打印,它代表当前设备的标准输出流流向,但是并不是写死的往控制台打印,它可以通过System的静态方法setOut改变其流向,同理我们也就推出了System.in和System.SetIn方法的使用规则和原理了。

希望我踩的这个坑能够帮助到你们(*^▽^*)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值