控制台的StreamTokenizer无限输入问题



我是Java的初学者,所以在我学习另一个主题StreamTokenizer期间,我遇到了一些有趣的问题。我没有在网上找到任何接近的解决方案或提示。

基本上,几乎所有的教育资源都给了我们这样的例子:

import java.io.*;
public class pr_23 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer st = new StreamTokenizer(br);

while (st.nextToken() != st.TT_EOF)
if (st.ttype == st.TT_NUMBER)
System.out.print(st.nval + " "); // not infinite cycle

br.close();
}
}

效果很好。但是如果我在循环中包含一些其他的st.nval操作符,比如double b = st.nval,并排除这个System.out.print()代码,编译器就不能确定在这种情况下流的结束,所以它开始无限读取。我想要StreamTokenizer给我的ArrayList数字,但神奇的是它不能看到流的结束,在这种情况下类似的循环。有趣的是,如果我使用FileInputStream而不是InputStreamReader,它确实可以正常工作。但我需要从控制台获得输入,而不是从文件。此外,不赞成在Tokenizer中使用FIS。下面是类似的代码,但是不能正常工作:

import java.io.*;
import java.util.ArrayList;
public class pr_23 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer st = new StreamTokenizer(br);

ArrayList<Integer> a = new ArrayList<>();

while (st.nextToken() != st.TT_EOF) {
a.add((int)st.nval);   // infinite cycle
}
System.out.print(a);

br.close();
}
}

注:为简单起见,输入只能是整型数字

请理解,您的循环正在重复,直到输入到达EOF。并且,在循环退出之前,后面的代码不会输出任何内容。因此,如果希望看到后一段代码的输出,必须首先关闭标准输入流。要关闭标准输入,您应该从键盘发送EOF代码。在Linux和macos上,你可以用Ctrl-D关闭标准输入,在Windows上,你可以用Ctrl-Z。

问题的根源是使用System.in

尝试从文件中读取:

import java.io.*;
import java.util.ArrayList;
public class pr_23 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("myfile.txt"));
StreamTokenizer st = new StreamTokenizer(br);

ArrayList<Integer> a = new ArrayList<>();

while (st.nextToken() != st.TT_EOF) {
a.add((int)st.nval);   // infinite cycle
}
System.out.print(a);

br.close();
}
}

问题是你不会在系统中得到EOF。如果你以交互方式运行它。如果你像这样运行它,你会得到它:

java pr_23  < myfile.txt
顺便说一下,没有悬空的close()的更好的写法是:
import java.io.*;
import java.util.ArrayList;
public class pr_23 {
public static void main(String[] args) throws IOException {
// using try this way will close br automagically
try (BufferedReader br = new BufferedReader(new FileReader("myfile.txt"))) { 
StreamTokenizer st = new StreamTokenizer(br);

ArrayList<Integer> a = new ArrayList<>();

while (st.nextToken() != st.TT_EOF) {
a.add((int)st.nval);   // infinite cycle
}
System.out.print(a);

}
}
}

最新更新