在输入输出的时候,会先将输入输出的东西放在一个文件里,这个文件也叫做 IO 设备
new
一个 Scanner
,在 Scanner
里面调用 next
的时候,程序会直接访问 IO 设备
。在调用一个 next
的时候,只会在 IO 设备中拿出一个数,再将这个数返回程序
调用一个 next
就会访问一次 IO 设备,程序访问 IO 设备的速度特别慢。所以当输入的数据量很大的时候,就会多次访问这个 IO 设备,所以就会超时
和 Scanner
读取数据一样。当输出数据的时候,也是将数据一个一个拿到 IO 设备中。由于程序访问 IO 设备的速度特别慢,所以只要数据量稍微多一些,就会超时
class Read{
StringTokenizer st = new StringTokenizer("");
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String next() throws IOException{
while(!st.hasMoreTokens()){
st = new StringTokenizer(bf.readLine());
}
return st.nextToken();
}
String nextLine() throws IOException{
return bf.readLine();
}
int nextInt() throws IOException{
return Integer.parseInt(next());
}
long nextLong() throws IOException{
return Long.parseLong(next());
}
double nextDouble() throws IOException{
return Double.parseDouble(next());
}
}
Java 在处理 IO 的时候,有两套标准:
System.in
)Reader
或者 Writer
)所以:
new InputStreamReader(System.in)
这里就是将字节流转换成了字符流
它是一个带内存缓冲区的字符流。将要读取数据的时候,先将 IO 设备里面的数据一次性放到这个"内存缓冲区中"。然后 BufferedReader
再调用 next()
的时候,就是直接在内存缓冲区里面拿数据的
这对比 Scanner
调用 next
之后,一次一次地重复在 IO 设备中读取数据来说,BufferedReader
在调用 next
的时候,只需要读取一次内存缓冲区,就能读取到所有数据。
这里是字符串裁剪。本质是拿到缓冲区中的数据,然后裁剪成一个一个的字符串,最后再转换成你想要的 int、long、double 等类型…
我们在这个类中,new
了一个 BufferedReader
,然后搞了一个字符串裁接
st = new StringTokenizer(bf.readLine());
我们这个字符串裁接传入的是 bf.readLine()
return st.nextToken();
这个对象向调用 next 返回的时候是 nextToken
最后再将这个字符串转换成你需要的数据类型即可
这里不需要 while 循环也行
String next() throws IOException{
st = new StringTokenizer(bf.readLine());
return st.nextToken();
}
直接读取一行数据,然后直接返回裁出来的字符串就行
但是这里为什么要加上 while 呢?
BufferedReader 相较于 System.in 快,就是因为他带了一个缓冲区。先把文件里面的数据刷新到缓冲区里面,然后在缓冲区里面拿一行一行的数据。随后通过 StringTokenizer 将读取的一行一行数据(
bf.readLine()
)一个个地进行裁剪工作。当后面还有的行时候,就一个一个的裁;当后面没有行的时候,就再重新读一行,一个一个地裁
public class Main{
public static PrintWiter out = new PrinterWriter(new BufferedWriter(new OutputStreamWriter(System.in)));
public static Read in = new Read();
public static void main(String[] args) throws IOException{
int t = in.nextInt;
double d = in.nextDouble;
//...
out.close;
}
}
Scanner
一样,正常直接调用即可new BufferedWriter(new OutputStreamWriter(System.in))
这里是把字符流转换为字节流
此处的 BufferedReader
是在输出的时候,不直接将数据从 IO 设备输出到程序,而是先将数据输出到内存缓冲区中,然后程序在内存缓冲区中直接读取数据(与输入原理一致)
其实 BufferedWriter
已经满足我们的需求了,为什么还要套一层 PrintWriter
呢?
BufferWriter
的输出方式不好写,而 PrintWriter
的输出方式和 System.out
是完全一样的(使用方式完全一样)