源代码见:点击打开链接
引言:在平时java开发中,被输入输出搞得头疼。特此写下这篇博客,一是为了总结输入输出,二是为了和大家分享。如果大家觉得写得好,就请高抬贵手点个赞呗!!!
1.输入格式,输出格式控制
1.1输入处理
java的输入,我们用到Scanner类,可以用它创建一个对象
Scanner reader=new Scanner(System.in);
然后reader对象调用nextBoolean(),nextByte(),nextShort(),nextInt(),nextLong(),nextFloat(),nextDouble()方法来从输入流中获取数据。这些方法在执行时都会阻塞,程序等待用户在输入流中输入enter键(\n)时继续执行。这里的nextInt,hasNextInt()这些方法的调用,会判断当前字节流里面是否有东西,没有就阻塞等待输入直到用户按enter键(\n)结束输入,在Scanner类中有一个变量needInput,当需要读取数据时,needInput=true(也就是调用nextInt,hasNextInt()这些函数的时候)。有一个readInput方法,当字节流中有东西可读时,让needInput=false(表示不需要阻塞等待输入);下面是Scanner.class源码:
// Tries to read more input. May block.private void readInput() {if (buf.limit() == buf.capacity())makeSpace();// Prepare to receive dataint p = buf.position();buf.position(buf.limit());buf.limit(buf.capacity());int n = 0;try {n = source.read(buf);//这儿} catch (IOException ioe) {lastException = ioe;n = -1;//这儿}if (n == -1) {sourceClosed = true;needInput = false;//这儿}if (n > 0)needInput = false;/这儿// Restore current position and limit for readingbuf.limit(buf.position());buf.position(p);}
总之,在调用next(),hasNext()方法时,字节流里面有东西,就不用等待,没有东西就阻塞等待。例如:
public static void main(String[] args) {// TODO Auto-generated method stubScanner s=new Scanner(System.in);int a,b;a=s.nextInt();System.out.println(a);b=s.nextInt();System.out.println(b);/*a=s.nextInt();b=s.nextInt();System.out.println(a+" "+b);*/}
当在命令行时输入时,我可以这样输入(在一行就输入两个数据再按enter),当运行到b=s.nextInt()时,发现字节流里面有东西,就没有阻塞等待输入了。
当然我们也可以这样输入(第一行输入2后,按enter键,然后在输入3,再按enter键)。运行过程是这样的,首先,当运行到a=s.nextInput()时发现,字节流里面没东西,等待输入,于是我们在命令行的第一行输入了2,按回车确认,这时程序继续执行。当运行到b=s.nextInt()时,发现字节流里面没东西,则阻塞等待输入,于是我们在命令行第三行输入3,按enter键确认,程序继续执行。
Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配(当然可以自定义分隔符)。
在下面1.3中我们举一个输入控制实例来熟练输入控制的使用。
1.2 hasNext源码解析
首先我们分输入源是System.in(也就是控制台),和从文件中读取(FileInputStream)。
(1)对于System.in,不管如何都是要返回true的。我们看源码:
/*这是测试代码*/Scanner scanner=new Scanner(System.in);while (scanner.hasNext()){System.out.println(scanner.next());}
我们进入hasNext()函数
public boolean hasNext() {ensureOpen();saveState();while (!sourceClosed) {/*看buffer里面是否有东西,有就返回ture*/if (hasTokenInBuffer())return revertState(true);/*没有就从System.in中读入数据。该方法可能会阻塞*/readInput();}/*对于从控制台中读入数据,这两句代码是永远不会被执行的。相当于从控制台读入数据永远不会结束,sourceClosed永远为false*/boolean result = hasTokenInBuffer();return revertState(result);
}
(2) 从文件中读取(FileInputStream)
Scanner scanner1=new Scanner(new FileInputStream("/home/fengli/a.txt"));while (scanner1.hasNext()){System.out.println(scanner1.next());}
在进入hasNext()方法:
public boolean hasNext() {ensureOpen();saveState();while (!sourceClosed) {/*看buffer里面是否有东西,有就返回ture*/if (hasTokenInBuffer())return revertState(true);/*没有就从System.in中读入数据。该方法可能会阻塞*/readInput();}/*用文件中读取,sourceClosed就可能为ture。所以这个方法就可以返回false*/boolean result = hasTokenInBuffer();return revertState(result);
}
1.3 输出处理
可用System.out.println()或System.out.print()来向屏幕进行输出。jdk1.5新增了和C语言中printf函数类似的数据输出方法,
System.out.printf(“格式控制部分”,表达式1,表达式2,……,表达式n)
格式控制部分由格式控制符号:%d,%c,%f,%s和普通字符组成,普通字符原样输出。格式控制符用来输出表达式的值。
%d:输出int类型数据值
%c:输出char类型数据
%f:输出浮点型数据,小数点部分最多保留6位
%s:输出字符串数据
%md:输出int型数据占m列
%m.nf:输出的浮点型数据占m列,小数点保留n位
格式字符串语法:
每个格式控制以%开始,以空格或标点符号结尾。
1.3输入输出实例--读入指定形状,输出指定形状
实例为输出九九乘法表,源码如下:
public class Main {public static void main(String[] args) {// TODO Auto-generated method stubfor(int i=1;i<=9;i++){for(int j=1;j<=i;j++){System.out.printf("%2d X%2d=%3d ",j,i,i*j);}System.out.println();}}
}
运行结果:
2.从文件输入,输出
2.1实现方法
可通过重定向标准输入输出流的方法来实现从文件中输入输出数据。具体使用到的方法如下:
static void setIn(InputStream in)//重定向标准输入
static void setOut(PrintStream out) //重定向标准输出
2.2从文件输入输出实例--拷贝
通过重定向的方法,实现从一个文件拷贝东西到另外一个文件。
代码如下:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Scanner;public class Main {public static void main(String[] args) {// TODO Auto-generated method stub/** FileInputStream里面的路径可以写绝对路径又可以写相对路径,为了程序的移植性,推荐使用相对路径,相对路径* 的根路径是Copy*/FileInputStream fis = null;PrintStream fos=null;try {fis = new FileInputStream("src/source");fos=new PrintStream("src/dest");} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.setIn(fis);//重定向标准输入//接下来就和从标准输入流读入数据一样了Scanner sc = new Scanner(System.in);String s=sc.nextLine();System.out.println(s);//重定向输出流System.setOut(fos);//接下来就和从标准输出流读入数据一样了System.out.println(s);}}