如何同时从键盘和文件中读取数据?

huangapple go评论71阅读模式
英文:

How do I read both from keyboard and from file?

问题

我有一个能够从键盘或文件(通过管道)读取的扫描器,显然没有办法区分是哪一种。

以下是我拥有的代码:

Scanner scan = new Scanner(System.in);
while (scan.hasNextLine()) {
	String line = scan.nextLine();
	doStuff();
}

当将输入重定向到文件时,这段代码运行得很好。但如果我尝试直接运行程序并从键盘读取,它会进入无限循环。有没有办法区分从键盘读取还是从文件读取?提前感谢!

编辑1:
按照 @Abra 的建议,这是我的代码外观:

Scanner scan = new Scanner(System.in);
do {
    String linea = scan.nextLine();
    doStuff();
} while (System.in.available() != 0 && scan.hasNextLine());

这是我正在运行的命令:

java -jar Class.jar < File.txt

编辑2:
问题解决了,原来我只需要对 System.in.available() != 0 进行一次判断:

Scanner scan = new Scanner(System.in);
boolean file = System.in.available() != 0;
do {
    String linea = scan.nextLine();
    doStuff();
} while (file && scan.hasNextLine());
英文:

I have a Scanner that could be reading from either keyboard or from a file (via pipes), and apparently there's no way to tell which.

I have te following code:

Scanner scan = new Scanner(System.in);
while (scan.hasNextLine()) {
	String line = scan.nextLine();
	doStuff();
}

That works wonderfully when redirecting input to a file. But if I try to run the program by itself and read from keyboard, it enters an infinite loop. Is there a way to differentiate between reading from keyboard and from a file? Thanks in advance!

Edit 1:
As requested by @Abra, this is what my code looks like with your suggestion:

Scanner scan = new Scanner(System.in);
do {
    String linea = scan.nextLine();
    doStuff();
} while (System.in.available() != 0 &amp;&amp; scan.hasNextLine());

And here's the command I'm running:

java -jar Class.jar &lt; File.txt

Edit 2:
Solved it, turns out I should only evaluate System.in.available() != 0 once:

Scanner scan = new Scanner(System.in);
boolean file = System.in.available() != 0;
do {
    String linea = scan.nextLine();
    doStuff();
} while (file &amp;&amp; scan.hasNextLine());

答案1

得分: 3

经典的在Linux和Unix中常用的做法是从标准输入读取输入,就像你已经在做的那样。在Java中,标准输入被称为 System.in

程序从标准输入读取内容,并在循环中处理它读取的内容,直到检测到文件末尾,这正是你已经在做的。

因此,你的程序并没有被卡住 - 它只是在等待更多的输入,或者等待外部发来的文件末尾信号。

如果你想要使用这个程序来处理来自文件的输入,你可以这样运行它:

myprogram < input_file.txt

如果你想让你的程序从终端获取输入(就是你在终端键入的内容),你可以像这样运行它:

myprogram

在这种情况下,在键入你的输入之后,你还需要负责从终端发送一个特殊的信号,这个信号将作为一个“文件末尾”被程序捕获,导致 while 循环退出。通常情况下,你可以通过按下Control-D来实现这一点。

请注意,从标准输入读取输入并不严格等同于从键盘读取输入。标准输入只知道文本和文件末尾;它不涉及行编辑,无法检测Shift键何时被按下/释放等操作。

英文:

The classic practice used commonly in Linux and Unix is to read input from standard input, as you are already doing. In Java, standard input is called System.in.

The program reads from standard input and processes what it reads in a loop until it detects end-of-file, which you are already doing.

So your program is not stuck - it is merely waiting for more input or for the end-of-file signal to come from the outside.

If you want to use this program with input from a file, you run it like this:

myprogram &lt; input_file.txt

And if you want your program to get its input from terminal (where you type it), you run it just like

myprogram

In this case, and after typing your input, you are also responsible to send a special signal from your terminal that will act as a "end-of-file" and will be picked by the program, causing the while-loop to exit. Typically, you do this by pressing Control-D.

Keep in mind that reading from standard input is not strictly the same as reading from keyboard. Standard input only knows about text and end-of-file; it has no concept of line editing, testing for when shift key is pressed/released etc.

答案2

得分: 1

基于 @Abra 的回答,如果 System.in 是键盘输入,你可以打破循环,如下所示:

import java.util.Scanner;
import java.io.IOException;

public class Main {
    public static void main(String[] argv) throws IOException {
        Scanner scan = new Scanner(System.in);
        boolean isKeyboard = System.in.available() == 0;
        while (scan.hasNextLine()) {
            String line = scan.nextLine();
            doStuff();
            
            if (isKeyboard) {
                break;
            }
        }
    }
}
英文:

based on the answer of @Abra you can break the loop if System.in is keyboard so:

import java.util.Scanner;
import java.io.IOException;

public class Main {
    public static void main(String[] argv) throws IOException {
        Scanner scan = new Scanner(System.in);
        boolean isKeyboard = System.in.available() == 0;
        while (scan.hasNextLine()) {
            String line = scan.nextLine();
            doStuff();
            
            if (isKeyboard) {
                break;
            }
        }
    }
}

答案3

得分: 1

System.in的类是java.io.InputStream。该类有一个方法叫做available()。如果你将System.in重定向到一个文件,就像下面这样:

myprogram < input_file.txt

那么available()方法会返回一个大于零的数字(假设input_file.txt的大小不为零),但是当System.in指向标准输入流,也就是在不重定向标准输入的情况下运行程序时,就像下面这样:

myprogram

那么available()方法会返回零。

英文:

The class of System.in is java.io.InputStream. That class has method available(). If you redirect System.in to a file, as in

myprogram &lt; input_file.txt

Then method available() returns a number greater than zero (assuming that input_file.txt has non-zero size) but when System.in refers to the standard input stream, i.e. when you run your program without redirecting standard input, as in

myprogram

Then method available() returns zero.

huangapple
  • 本文由 发表于 2020年10月25日 17:50:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/64522356.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定