设为首页 加入收藏

TOP

Java I/O操作入门教程(一)
2014-11-23 19:52:57 】 浏览:511
Tags:Java I/O 操作 入门教程

Java 提供的标准模型有 System.in, System.out, System.err。平日里我们经常用到他们3个,其中用的最多的就是System.out.println()等了,最近突然想到,他们是怎么实现的呢?


下面是JDK中者三者的定义的源码:
public final static InputStream in = nullInputStream();


public final static PrintStream out = nullPrintStream();


public final static PrintStream err = nullPrintStream();


从上面的代码上我们可以用到,除了in,其他两者都已经封装成了PrintStream格式,我们可以直接使用他们。而in则有点特殊,它只是一个没有被包装过的未经加工的InputStream(这是Thinking in java的原话,但是在实际我发现,这个InputStream的真实类型应该是BufferedInputStream,有可能是我对这句话的理解有误导致的吧),鄙人在学C++的时候,依稀记得,当出现cin>>这样的标识的时候,程序会停下来等待键盘的输入操作,但是在Java中用起来要费劲些,直接这么简单粗暴的输入,是没有效果的。


一般情况下,我们需要对其进行包装,下面的例子就是其中的一个方法


InputStream in = System.in;
BufferedReader stdin = new BufferedReader(new InputStreamReader(in));//对其进行包装
System.out.print("请输入字符: ");
String str = stdin.readLine();//等待键盘输入,按回车结束
System.out.println("你输入的字符为: " + str);


回到开篇讲到的内容,我们注意到in,out返回的是方法 nullInputStream()、nullPrintStream()方法执行后的结果,我第一次看的时候,想当然就以为这两个方法返回的是inputStream、和PrintStream。后来走到源码中一看,才傻眼了,这两个方法是这样的


/**


* The following two methods exist because in, out, and err must be


* initialized to null. The compiler, however, cannot be permitted to


* inline access to them, since they are later set to more sensible values


* by initializeSystemClass().


*/


private static InputStream nullInputStream() throws NullPointerException {


if (currentTimeMillis() > 0) { //一般情况下,不会出现<=0的情况


return null;


}


throw new NullPointerException();


}



private static PrintStream nullPrintStream() throws NullPointerException {


if (currentTimeMillis() > 0) {


return null;


}


throw new NullPointerException();


}



  从上段代码中我们可以看到,其实这两个方法返回的是null(或者是出现一个运行时的异常)。那么问题来了,竟然是null值,那它们是如何操作与初始化的。


好在,方法之前有一大段的注释,说明这连个方法之所以存在时应为in,out等必须初始化为空(why 等待高手解答啊。。。),那么何时才是真正的执行初始化操作呢?


答案就在initializeSystemClass()这个方法里


/**


* Initialize the system class. Called after thread initialization.


*/


private static void initializeSystemClass() {


props = new Properties();


initProperties(props);


sun.misc.Version.init();



// Load the zip library now in order to keep java.util.zip.ZipFile


// from trying to use itself to load this library later.


loadLibrary("zip");



FileInputStream fdIn = new FileInputStream(FileDescriptor.in);


FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);


FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);


setIn0(new BufferedInputStream(fdIn));


setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));


setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true));


/**


* 以上只是部分代码,下面是无关的代码,略去


*/



  在上面这段代码里,setIn0等方法的代码如下


private static native void setIn0(InputStream in);
private static native void setOut0(PrintStream out);
private static native void setErr0(PrintStream err);


可以看到上面这三个方法都是native方法,那么我们就不能继续跟下去了,但是我们可以看setIn,setOut,setErr方法,我们知道,这三个方法用于冲定向标准的I/O流。


public static void setIn(InputStream in) {


checkIO(); //用于权限的检查


setIn0(in);


}



public static void setOut(PrintStream out) {


checkIO();


setOut0(out);


}



public static void setErr(PrintStream err) {


checkIO();


setErr0(err);


}



  这三个方法都调用了相应的setXX0()方法,由此我们可以推出setIn0等方法用于重定向输入输出流。


那么重定位到哪呢? 答案就是


new FileInputStream(FileDescriptor.in)


new FileOutputStream(FileDescriptor.out)


new FileOutputStream(FileDescri

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Shell脚本实现DB2数据库表导出到.. 下一篇TQ2440触摸屏驱动程序的移植

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目