A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 曹昌豪 中级黑马   /  2012-5-28 13:23  /  1813 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

一直不明白System.setOut            System.setIn    这俩的情况,重新分配标准输入流和标准输出流,这到底是怎么做的,搞不明白啊,所以一般回避这个,求支招!!!!!

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

3 个回复

倒序浏览
System.setIn(InputStream in) 分配标准输入流为参数in指向的文件,System.in指向的就由默认的键盘改为in所指的文件
File f = new File("e:" + File.separator + "123.txt");
System.setIn(new FileInputStream(f));
InputStream in = System.in;
byte[] b = new byte[1024];
int len = in.read(b);
in.close();
System.out.println(new String(b, 0, len));

System.setOut(PrintStream out)重新分配“标准”输出流。
System.setOut(new PrintStream("文件路径"));
System.out.println("Hello World");//输出到了文件

提前定义System.in引用恢复默认键盘输入:
InputStream   old   =   System.in;
//System.setIn();
System.setIn(old);
定义System.out的引用恢复默认显示器输出:
PrintStream out = System.out;
//System.setOut();
System.setOut(out);

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

回复 使用道具 举报
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter  bufw = new BufferedWriter(new OutputStreamWriter(System.out));

以上两句中,源设备是键盘,目的是控制台。
通过System.setIn(new FileInputStream("abc.txt"));这句语句后源设备就变成了文件了,也就是硬盘。
通过System.setOut(new PrintStream("zzz.txt"));这句后目的地就由控制台变成了硬盘了。

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

回复 使用道具 举报
感谢楼主提出的问题,我开始以为楼主要知道setIn的原理,所以查看了System的源代码,又学到一些东西,现在拿来和大家分享一下
先上有关
    public static void setIn(InputStream in) {
        checkIO();
        setIn0(in);
    }
    private static void checkIO() {
        SecurityManager sm = getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("setIO"));
        }
    }
   private static native void setIn0(InputStream in);
前面的checkIO很好的解释了API中的这段话。
首先,如果有安全管理器,则通过 RuntimePermission("setIO") 权限调用其 checkPermission 方法,查看是否可以重新分配“标准”输入流。
关键是这样一个setIn0,没有方法体的方法,一般如果是抽象方法的话这就能解释了,但是System这个类是final的,也就是说不能被继承,那它怎么能有抽象方法呢?
通过查找百度,发现这样一个网页写的十分详细http://karoii.bokee.com/5869823.html
以下是摘抄的其中几句。
Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。
  可以将native方法比作Java程序同C程序的接口,其实现步骤:
  1、在Java中声明native()方法,然后编译;
  2、用javah产生一个.h文件;
  3、写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件);
  4、将第三步的.cpp文件编译成动态链接库文件;
  5、在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。
那么这里我记住了如果要提升性能的话,我们也可以自定义native方法。不过到底怎么做到用的时候再翻也来的及。

还有一个问题是这个方法在哪里?在jdk的lib目录下的jvm.lib文件中就有这些native方法的实现,我的理解是在include目录下的.h文件中一定有这些函数
的声明,不过我怎么找都找不到,如果老师能看到希望能指教下。
至于怎么用就很简单了,而且我可以告诉lz,在System这个类中有这个函数private static void initializeSystemClass(){}
其中有一段FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
        setIn0(new BufferedInputStream(fdIn));
可以看到,System初始化的时候也调用了这个函数,和上面两位同学的用法并无不同,所以我们的标准输入输出一开始就是控制台和键盘,如果改掉这些代码的话,呵呵。
       
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马