Java蓝桥杯输入输出方法总结

在蓝桥杯竞赛中,合适的输入输出方法对提高程序运行效率至关重要。本文将系统地介绍Java中各种输入输出方法,并提供性能对比分析。

1. Scanner类

1.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);

// 读取整数
int n = sc.nextInt();

// 读取字符串
String str = sc.next();

// 读取一整行
String line = sc.nextLine();

// 读取浮点数
double d = sc.nextDouble();

sc.close();
}
}

1.2 优缺点

  • 优点:使用简单,功能齐全
  • 缺点:性能较差,不适合大量数据的输入

2. BufferedReader类

2.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

// 读取一行字符串
String line = br.readLine();

// 读取整数
int n = Integer.parseInt(br.readLine());

// 读取空格分隔的多个整数
String[] nums = br.readLine().split(" ");
int[] arr = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
arr[i] = Integer.parseInt(nums[i]);
}

br.close();
}
}

2.2 优缺点

  • 优点:效率高,适合处理大量数据
  • 缺点:使用相对复杂,需要处理IOException

3. StreamTokenizer类

3.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.io.IOException;

public class Main {
public static void main(String[] args) throws IOException {
StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

// 读取数字
st.nextToken();
int n = (int) st.nval;

// 读取字符串
st.nextToken();
String str = st.sval;
}
}

3.2 优缺点

  • 优点:自动分词,处理数字和字符串方便
  • 缺点:使用较为复杂

4. 快读快写模板

4.1 基于BufferedReader的快读模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.io.*;

class FastReader {
private BufferedReader br;
private StringTokenizer st;

public FastReader() {
br = new BufferedReader(new InputStreamReader(System.in));
}

public String next() {
while (st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}

public int nextInt() {
return Integer.parseInt(next());
}

public long nextLong() {
return Long.parseLong(next());
}

public double nextDouble() {
return Double.parseDouble(next());
}

public String nextLine() {
String str = "";
try {
str = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
}

public class Main {
public static void main(String[] args) {
FastReader fr = new FastReader();
int n = fr.nextInt();
long m = fr.nextLong();
double d = fr.nextDouble();
String s = fr.next();
String line = fr.nextLine();
}
}

4.2 基于字节流的极速读写模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import java.io.*;

class UltraIO {
private static final int BUFFER_SIZE = 1 << 16;
private final DataInputStream din;
private final DataOutputStream dout;
private final byte[] buffer;
private int bufferPointer, bytesRead;

public UltraIO() {
din = new DataInputStream(System.in);
dout = new DataOutputStream(System.out);
buffer = new byte[BUFFER_SIZE];
bufferPointer = bytesRead = 0;
}

public String readLine() throws IOException {
byte[] buf = new byte[64]; // 用于存储输入的字符
int cnt = 0, c;
while ((c = read()) != -1) {
if (c == '\n') break;
buf[cnt++] = (byte) c;
}
return new String(buf, 0, cnt);
}

public int nextInt() throws IOException {
int ret = 0;
byte c = read();
while (c <= ' ') c = read();
boolean neg = (c == '-');
if (neg) c = read();
do {
ret = ret * 10 + c - '0';
} while ((c = read()) >= '0' && c <= '9');
if (neg) return -ret;
return ret;
}

private void fillBuffer() throws IOException {
bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
if (bytesRead == -1) buffer[0] = -1;
}

private byte read() throws IOException {
if (bufferPointer == bytesRead) fillBuffer();
return buffer[bufferPointer++];
}

public void close() throws IOException {
if (din == null) return;
din.close();
}
}

public class Main {
public static void main(String[] args) throws IOException {
UltraIO io = new UltraIO();
int n = io.nextInt();
String line = io.readLine();
io.close();
}
}

5. 性能对比

以下是各种输入方法读取100万个整数的性能对比:

  1. Scanner:约2000ms
  2. BufferedReader:约500ms
  3. StreamTokenizer:约400ms
  4. FastReader:约300ms
  5. UltraIO:约150ms

6. 使用建议

  1. 对于简单题目或数据量较小的情况,使用Scanner即可
  2. 对于数据量中等的题目,使用BufferedReader或FastReader
  3. 对于数据量极大或对时间要求极高的题目,使用UltraIO模板
  4. 在实际比赛中,建议将快读模板代码准备好,以备不时之需

7. 注意事项

  1. 使用Scanner时注意nextInt()和nextLine()混用可能导致的问题
  2. BufferedReader必须处理IOException
  3. 在使用完输入流后记得关闭(close)
  4. 对于竞赛中的多组输入,注意处理输入结束的条件

总结

在蓝桥杯竞赛中,选择合适的输入输出方法可以显著提高程序的运行效率。对于不同的题目要求,应当灵活选择合适的输入方法。建议平时多加练习各种输入方法的使用,以便在比赛中得心应手。