Piping Input using Java using command line - java

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.

Related

Why does my code stuck in eclipse at readLine()?

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.

How do we take command line arguments using arg[] from intellij/eclipse

I was asked to run a program using command line arguments. The command line argument could either be a file or stdin.
eg:
Your program must accept input from two sources: a filename passed in
command line arguments and STDIN. For example './program input.txt' and './program < input.txt' should work.
Let me be frank, I am not sure whether I am being asked to pass the location of the file or feed the input to the program using STDIN. I am assuming, for now, it's asking me to input the location of the file. How can I do it using arg[0]? Can I use System.in, will that violate the requirement that is being asked from me?
Instead of running the application directly you can pass the arguments from run configuration. For example, in eclipse you can do the following:
right click on the project > run as > run configuration
In the new windows: java application > "your app"
you can find a tab "arguments"
here you can set the arguments for the app in the "program arguments".
I am not sure whether I am being asked to pass the location of the file or feed the input to the program using STDIN
Both. As stated, "your program must accept input from two sources". So, your program must support both, either taking a file argument or reading from standard in.
For the first variant, the file argument, the file's name will be available in arg[0].
So, if the arg-array contains at least one entry, go with the file argument.
If there is no file argument (arg.length == 0), then read from STDIN.
In code, it could look a bit like this:
public static void main(String[] arg) {
if (arg.length == 0) {
// work with System.in
} else {
File file = new File(arg[0]);
// work with file
}
}

Eclipse Hanging on Scanner File Redirection (java)

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.

Using files as arguments for a Java program in the terminal

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.

How does the Java program know how to access the file?

I have been reading this book Algorithms 4th Edition. Its code examples take an input from the command line
String[] a = StdIn.readAllStrings();
and sorts them. The source code for StdIn.java is given in http://introcs.cs.princeton.edu/java/stdlib/StdIn.java . Source for heap sort is in http://algs4.cs.princeton.edu/24pq/Heap.java but really isn't relevent.
The main function looks like this:
public static void main(String[] args) {
String[] a = StdIn.readAllStrings();
Heap.sort(a);
show(a);
}
There is no explicit reference to the args. Yet when i pass in a text file as an argument in the command line it works as advertised:
% more tiny.txt
S O R T E X A M P L E
% java Heap < tiny.txt
A E E L M O P R S T X
Can someone enlighten me how the program reads in the input when no reference has been given. Many thanks in advanced!
Edit: changed the link for stdin java. My bad.
You've got this rather wrong:
"The source code for StdIn.java is given in http://introcs.cs.princeton.edu/java/stdlib/In.java."
Actually the source code for StdIn.java is http://introcs.cs.princeton.edu/java/stdlib/StdIn.java. You were looking at the wrong class!
"Yet when i pass in a text file as an argument in the command line it works as advertised".
Actually, you are NOT passing a text file as an argument. Really!
When you do this:
% java Heap < tiny.txt
the shell is opening the file, and passing the open file descriptor to Java. Java wraps this file descriptor as an java.io.InputStream object, and makes it available for the application via the the java.lang.System.in variable. That is what StdIn.readAllStrings() is actually reading from.
In fact, your Heap program has no command line arguments. If you print args.length in the main method, you will see that it is zero.
When in command line, passing a file as < whatever to the application means that the contents of the whatever file will be the input for the application. This means that the contents of tiny.txt (in your specific case) will become the t̶e̶d̶i̶o̶u̶s̶ user input of the application.
Looking at the default constructor for the In class you provided, I assume StdIn is just an instance which is default initialized. By this constructor, it reads from stdin. By redirecting stdin to be from a file (<), you are feeding the contents of the file to this reader which is simply reading the lines.
To be clear, the text file is not given to your program in the args array. That would be java Heap sort.txt. Instead the standard input stream is redirected to be from a file.

Categories