标题:一个小问题,关于流的关闭和开启(求助)
只看楼主
hsjjgm
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:106
专家分:189
注 册:2013-4-27
结帖率:88.89%
已结贴  问题点数:20 回复次数:9 
一个小问题,关于流的关闭和开启(求助)
我搞了一个下工具类,专门从键盘读取字符串,代码如下:
public class KeyboardIO
{
    //从键盘获取字符
    public static String getString()
    {
        String s;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try
        {
            print("请输入字符");
            s = br.readLine();
            return s;
        } catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally
        {
            try
            {
                br.close();
            } catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return null;
    }
我顺便也写了个获取数字的方法
//获取数字
    public static int getInteger()
    {
        int time = 3;
        while(time-- > 0)
        {
            String s = getString();
            if(s.matches("\\d+"))
                return Integer.parseInt(s);
            else
            {
                print("输入非法字符,请重新输入");
                print("您还有" + time + "次机会没," + "请重新输入");
            }
        }
        print("错误次数超过限制,获得数字失败");
        return -1;
    }
不过问题来了,我发现如果第一个读取字符串的方法不能读第二次,只能读一次,这是为什么呢?(会提示流已经被关闭了的异常)
虽然退出方法之前流被关闭了,但是第二次执行方法时,执行了new语句,应该会重新开启的啊,难道不是这样么?
搜索更多相关主题的帖子: public return 字符串 键盘 
2013-08-28 11:26
ren829
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:15
帖 子:255
专家分:1174
注 册:2006-3-11
得分:5 
想着可以继续读取,你要继续调用getString方法才行,这个动作你做了吗?
2013-08-28 18:16
hsjjgm
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:106
专家分:189
注 册:2013-4-27
得分:0 
回复 2楼 ren829
while(time-- > 0)
        {
            String s = getString();
            if(s.matches("\\d+"))
                return Integer.parseInt(s);
            else
            {
                print("输入非法字符,请重新输入");
                print("您还有" + time + "次机会没," + "请重新输入");
            }
        }
这里不是有个循环么,失败了会继续循环调用啊getString()啊
而且我调试的时候看到执行过new啊,咋还是提示关闭呢
2013-08-29 01:08
hsjjgm
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:106
专家分:189
注 册:2013-4-27
得分:0 
莫有人指教下么
2013-08-30 22:57
ren829
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:15
帖 子:255
专家分:1174
注 册:2006-3-11
得分:0 
你也不能每次读取,不管读取的对错就关闭一次啊,完全可以读取完了再关闭。time变成全局变量,关闭流的时候加一个if(br!=null&&time<=0){br.close();}
 
还有这块 if(s.matches("\\d+"))也加一个判断,s!=null。不然你读取错误的时候,这块也是抛空指针异常的。
2013-08-31 16:10
ren829
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:15
帖 子:255
专家分:1174
注 册:2006-3-11
得分:0 
这个问题还挺有意思的,我也挺奇怪为什么会关闭后在开启一个流会抛出已经关闭异常,后来我打印了下 System.in 的地址,呵呵,发现调用两次的地址完全是一样的。
所以说,这个流关闭后,再用BufferedReader 包装一次,其实是把一个已经关闭的流包装了一次,所以会提示流已经关闭的错误。
2013-08-31 16:35
Kingbox_tang
Rank: 7Rank: 7Rank: 7
来 自:天津师范大学
等 级:黑侠
威 望:3
帖 子:146
专家分:677
注 册:2012-11-27
得分:5 
这方面我学习了,谢谢

旨在提高编程水平,学有所用,学有所成,学有所为。
2013-09-02 11:42
zrqvery158
Rank: 2
等 级:论坛游民
帖 子:28
专家分:68
注 册:2013-8-23
得分:5 
我也糊涂了
2013-09-02 15:19
iikhsyy
Rank: 1
等 级:新手上路
帖 子:1
专家分:5
注 册:2013-9-2
得分:5 
BufferedReader 是对system中的静态字段in所指向的对象的包装,因为是静态的所以只在第一次调用时在静态区初始化一次,而BufferedReader 的close方法调用了所包装对象的close方法,最终调用的就是in的close方法,由于in是静态的字段,其指向的对象全局共享只有一个,所以in调用close方法后,这个流就关闭了,即使你新建BufferedReader 对象也只是对这个已经关闭了的in的包装。如果你用一个继承了BufferedReader 的类来对system.in进行包装,然后对这个继承类中的close方法进行重写并不调用super.close以及所包装对象的close方法的话,就可以是看到即使调用了close方法也不会报错。而如果在继承类中重写的close方法中调用了所包装对象的close方法的话,同样的错误就会再次出现。


[ 本帖最后由 iikhsyy 于 2013-9-3 15:29 编辑 ]
2013-09-02 18:09
ren829
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:15
帖 子:255
专家分:1174
注 册:2006-3-11
得分:0 
楼上的解释很直接了,是问题的根本。
2013-09-02 22:15



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-419753-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.095866 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved