ACM javaIO 快速 读写

在这里先比较一下三种输入方式(这里从文件中读取):
第一种,Scanner类读取文件(in.txt,里面有从一到一百万的的整数)

public class Main {
	public static void main(String[] args) throws IOException{
		Scanner sc = new Scanner(new FileInputStream("in.txt"));
		long start = System.currentTimeMillis();
		for(int i=1;i<=1000000;i++)
			sc.nextInt();
		long end = System.currentTimeMillis();
		System.out.println("time="+(end-start)+"ms");
	}
}

运行结果:

time=2930ms   

大概3秒,实际上如果ACM中真有一百万的数据,若用Scanner读取,还没开始计算,就已经超时了。

第二种,网上说的petr大佬的模板

public class Main {
	public static class InputReader{
		private BufferedReader in;
		private StringTokenizer tokenizer;
		public InputReader(InputStream stream){
			in = new BufferedReader(new InputStreamReader(stream),32768);
			tokenizer = null;
		}
		public String next() throws IOException{
			while(tokenizer==null || !tokenizer.hasMoreTokens()){
				tokenizer = new StringTokenizer(in.readLine());
			}
			return tokenizer.nextToken();
		}
		public int nextInt() throws IOException{
			return Integer.valueOf(next());
		}
	}
	public static void main(String[] args) throws IOException{
		InputReader reader = new InputReader(new FileInputStream("in.txt"));
		long start = System.currentTimeMillis();
		for(int i=1;i<=1000000;i++)
			reader.nextInt();
		long end = System.currentTimeMillis();
		System.out.println("time="+(end-start)+"ms");
	}
}

运行结果:

time=844ms

显然读取速度提高了两秒,已经在ACM允许的时间内了。

第三种,用StreamTokenizer读取

public class Main {
	public static StreamTokenizer in;
	static {
		try{
			in = new StreamTokenizer(new BufferedReader(new InputStreamReader(new FileInputStream("in.txt"))));
		}catch (Exception e){
			e.printStackTrace();
		}
	}
	public static int nextInt() throws IOException{ in.nextToken(); return (int)in.nval; }
	public static void main(String[] args) throws IOException{
		long start = System.currentTimeMillis();
		for(int i=1;i<=1000000;i++)
			nextInt();	//这里仅读取,不输出
		long end = System.currentTimeMillis();
		System.out.println("time="+(end-start)+"ms");
	}
}

运行结果:

time=397ms

速度相比petr大佬的模板,速度又快了一倍左右。
不过要注意的是,用StreamTokenizer读取字符串时,只能读取纯字母字符串,如果包含数字或者其他字符会返回null。这是用StreamTokenizer读取的缺点。但是用它读取数字时没有问题的。

总结一下:
如果数据量比较小,用Scanner是比较方便的
如果数据量很大的话,那么用StreamTokenizer 是一个很好的选择
至于petr大佬的模板,从代码量和运行时间上都不如StreamTokenizer ,不推荐使用

输入讲完了,这里再比较一下两种输出方式

第一种使用传统的System.out.println()方式输出。

public class Main {
	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		for(int i=0;i<100000;i++)
			System.out.println(i);
		long end = System.currentTimeMillis();
		System.out.println("time="+(end-start)+"ms");
	}
}

运行结果:

...
......
time=3443ms

显然在ACM中会超时

第二种使用PrintWriter输出:

public class Main {
	public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		for(int i=0;i<100000;i++)
			out.println(i);
		out.flush();
		long end = System.currentTimeMillis();
		System.out.println("time="+(end-start)+"ms");
		out.close();
	}
}

结果:

..
....
time=328ms

虽然每次输出的结果会有大致几十毫秒的偏差,但总体上来看,PrintWriter输出要比用System.out.println()输出快上10倍左右。这个结果就比较让人满意了。

最后在这里提供一个ACM模板:

import java.io.*;

public class Main {
	public static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in),32768));
	public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

	public static double nextDouble() throws IOException{ in.nextToken(); return in.nval; }
	public static float nextFloat() throws IOException{ in.nextToken(); return (float)in.nval; }
	public static int nextInt() throws IOException{ in.nextToken(); return (int)in.nval; }
	public static String next() throws IOException{ in.nextToken(); return in.sval;}

	public static void main(String[] args) throws IOException{
//		获取输入
		while(in.nextToken()!=StreamTokenizer.TT_EOF){
			break;
		}
		int x = (int)in.nextToken();  //第一个数据应当通过nextToken()获取
		
		int y = nextInt();
		float f = nextFloat();
		double d = nextDouble();
		String str = next();

//		输出
		out.println("abc");
		out.flush();
		out.close();
	}
}

参考
1、晒一个Java的快速io代码
2、java ACM竞赛IO优化Petr模板

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值