I was working on a program that involved taking input from STDIN with the intention of always having the input redirected from a file. My method of doing so was to use the scanner class to read by line, and perform some string operation.
I am currently doing this in eclipse neon. I am using the run configurations > common > input file option to automate redirection on running the program and just letting the output print to the console.
What I am finding is that every time I run the program, the code hangs on the last line of the file, and will not terminate until I signal EOF with ctrl+z (windows). I went back and opened some old projects and noticed the same trend and am confident they didn't have this problem before and haven't changed the code. Below is a code example:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s;
String everything = "";
while(sc.hasNextLine()){
s = sc.nextLine();
everything.concat(s);
System.out.println(s);
}
System.out.println(everything);
sc.close();
}}
It seems like hasNextLine() is blocking as it waits for input, but as I terminate it prints the final line of the file and never prints 'everything'.
Example input file im using looks like:
1
2
3
4
The program prints 1, 2, 3 on separate lines, but will not print 4 until I signal EOF. My understanding of hasNextLine() is that when redirected, it should recognize EOF and stop blocking.
EDIT: The problem seems to be independent of hasNextLine() blocking as I am redirecting a file. hasNextLine() should not block on file redirection as the file should signal EOF. The problem seems related to eclipse.
Related
Full disclosure, I'm new to java but I couldn't find a fix that worked for my problem.
I'm making a text adventure as practice for school and i'm simply trying to get input from the user using java.util.Scanner which works perfectly in a separate method of the same class while using almost the exact same code.
I keep getting the exception:
java.util.NoSuchElementException: No line found
It seems to be because the program isn't waiting for user input.
I tried adding an if else statement to check if there was any input in the scanner when the program should set a string type variable to it's contents and It always comes up empty.
The problem code:
System.out.println("In which direction would you like to move?");
Scanner reader = new Scanner(System.in);
String sDirection = reader.nextLine(); //This line specifically.
reader.close();
Yet this code works fine:
System.out.println("Do you accept this quest?(y/n)");
Scanner reader = new Scanner(System.in);
String sTemp = reader.nextLine();
reader.close();
char answer = sTemp.charAt(0);
return answer;
In the problem code the scanner should record the user's input (north, south, east or west), sDirection is then set to that string and used in an if else statement. However, the program returns the "No line found" exception before the user gets a chance to input anything.
Stop closing scanner. When you do this it close underlying stream, so no further reading is possible.
Remove reader.close(); from all your code.
Also you should create Scanner only once and pass it to method which need it.
Remove reader.close(); from your code.
It will work if you want to close the scanner object, you can close where your main method ends and there only you can close it.
And you should create Scanner only once and call it where it needs.!
I'm creating a simulation of an NFA and i'm supposed to read from a standard input. I have full working code(Works fine while called from Windows PowerShell script) which doesn't run in Eclipse IDE becuse it stops at second line where is suppsoed to read a line from a stdin. I have stored input in Program arguments and run the program with it.
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String s = reader.readLine(); //HERE CODE STOPS
String InputStrings[] = s.split("\\|");
int NumberOfInputStrings = InputStrings.length;
...
I'd like to know what's happening behind this and why this doesn't work.
You need to enter the value in the console to read it. It is stopped because it is waiting for your input to provide and read it.
Well, you have to provide the input so the reader can read it. Run the code and in the Eclipse console type something and press Enter.
java someJavaProgram fsa.fsa <test.txt
That, apparently, is a legitimate command to take with two files as arguments for a Java program in the terminal - one to read in, and then the other (and I think the idea is that it prints the output to the terminal directly). someJavaProgram, fsa.fsa and test.txt are all files in the same directory (being someProject/src, and someJavaProgram in the default package).
However, the response I am given in the terminal just says:
FSA file not found - please scan in the appropriate file.
Testing file not found, please scan in the new relevant file.
My question is two-fold:
What is this command and what is it for?
Does it need refining or modifying or is it the program that needs improvement?
I should note that I wrote the code in Eclipse, where I simply hardcoded filepaths into the program. I'm not sure if that affects anything but it's related.
EDIT: The filepaths and related code are as follows:
private static final String FILE_PATH = "src/test.txt";
private static final String FSA_PATH = "src/fsa1.fsa";
...
public static void main(String[] args) throws FileNotFoundException {
interpretAutomaton();
testAutomaton();
}
...
interpretAutomaton() {
...
Scanner fsaScanner = new Scanner(new BufferedReader(new FileReader(FSA_PATH)));
...
testAutomaton() {
...
Scanner fileScanner = new Scanner(new BufferedReader(new FileReader(FILE_PATH)));
*Both are surrounded by try/catch blocks - which clearly work!
Thanks to anyone who can help clarify on the matter!
Based on the comments so far, to answer your actual questions:
1) The command has four elements:
java - execute the java program
someJavaProgram - the name of the Java class to execute
fsa.fsa - the first argument to the java program, accessible via argv[]
<test.txt - standard input redirection, the contents of the file will be available on the program's standard input, ie. System.in
The net effect is to run your Java program with one argument and one file's contents on the standard input.
2) Both the command line and the program look like they need to change:
change the command line to:
java someJavaProgram fsa.fsa test.txt
That is, remove the <. You will also need to check the paths to the files are correct. This command line assume you are in the same directory as the files when you execute it.
Change your code to use the filenames on the command line rather than the hard-coded names.
public class ReadInput {
public static void main(String[] args) throws IOException {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String x = null;
while( (x = input.readLine()) != null ) {
System.out.println(x);
}
}
}
I am able to run this code from the command line by typing 'java ReadInput < input.txt' but not by typing the input directly like 'java ReadInput hello'. When I type 'java ReadInput hello' I seem to get stuck in an infinite loop for some reason. Shouldn't it just work in the same way as typing 'java ReadInput < input.txt' but instead just reprint 'hello'?
Arguments given on the program's command line don't go to System.in, they go in the args array. You could use something like echo hello | java ReadInput to run the program, or you could modify the program to to look at its args array and treat it as input. (If you use the latter option, you'd probably want to fall back to reading from System.in if there's nothing in args.)
Both of the other two answers above are partially correct, but partially misleading.
Using the following syntax...
java ReadInput < input.txt
...the actual command that is run on the java binary is:
java ReadInput
The operating system shell interprets the < sign, and sends the contents of input.txt to the Standard Input Stream (System.in).
When you call System.in.readLine(), the code checks whether there is a line of input available from the Standard Input Stream. When you piped in a file, this means it takes the next line of the file (as if the OS were taking the contents of the file and typing them in at the prompt). When you run the program without piping a file, it will wait until you, the user, provide it with a line of input from the shell and press the return key.
Command-line arguments to the JVM work differently, and do not use the Standard Input Stream (System.in). Ex:
java ReadInput "Input number one" "Input number two"
In this case, you are passing in two command-line arguments. These properties will be available through the args array:
public static void main(String[] args) throws IOException {
System.out.println(args.length); //3
System.out.println(args[0]); //"ReadInput"
System.out.println(args[1]); //"Input number one"
System.out.println(args[2]); //"Input number two"
}
With the code that you provided, the program will end when the result of a readLine() call returns null. I believe you may be able to just push enter at the prompt to send a blank line, and end the program. If not, you may have to fix the program to check for an empty string (input.readLine().equals("")).
Hope this helps.
When you type java ReadInput hello you have not (yet) provided any input to System.in so the program execution blocks until there is something to read. You might notice that the string "hello" is passed into the args parameter to the main() method.
If you're using a debugger (which I strongly recommend), place a breakpoint at the first line of main(). You'll notice that, when you run your program as java ReadInput hello that args[0] is "hello".
If you're not using a debugger, you can use System.out.println() (this is how beginners frequently debug their code). Add this line of code as the first line of main():
if (args.length > 0) System.out.println(args[0]);
Terminate the standard input with
Ctrl-D : Linux/Unix
Ctrl-Z (or F6) and "Enter" : Windows.
Or set a special EOF symbol youself.
I'm currently working on a programming assignment for school. It's a simple text-based RPG. When I test the program locally (by hand), it works correctly. However, when I submit it to the grading server, it creates some sort of infinite loop.
I emailed my professor, who responded by explaining how the server tested the program. It uses the following format: java IPA1 (XML file name) < (Input file) > (output file). IPA1 is the name of the main java file. It seems that the < (Input file) is causing the endless loop for some reason... but I cannot pinpoint why.
My program gets its input with the following code:
boolean gameOver = false;
while (!gameOver) {
Command cmd = inputParser.getCommand();
gameOver = processCommand(cmd);
}
The getCommand(cmd) is as follows:
public Command getCommand() {
String input = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
input = reader.readLine();
} catch(java.io.IOException exc) {
System.out.println ("Error");
}
return new Command(input);
}
My question is: Why would this work when I type each command in sequentially by hand... but fail when an input file is used?
This is because you are creating a buffered reader that reads more than you requested it to read. When you tell it to read five characters, it reads a lot more and saves them for the next request to boost performance. You should reuse one BufferedReader instead of creating many of them because when you create many of them, the first one already grabs stuff you want to read with the second one.
Try printing out what you read - there might be new line symbol at the end of the string or something is different about the file, so it doesn't exit from the loop. You can also debug the program to see exactly what's happening.
If you want exact answer to why in this case it doesn't work you need to post the
processCommand() function and the content of the file.