Running Java program via Command Prompt with input and output files - java

I have a program that is supposed to take inputs from the commandline and direct them to standard input and direct the output to standard output. The code supposed to be entered into the commandline is meant to look as follows:
java package.sub.Calc < input-file > output-file
or
echo some inputs to the calculator | java
package.sub.Calc
But I can't seem to get it to work correctly. The goal is to be able to pass a text file into the program or write your math problems right there on the command line and pipe it in.
The program runs correctly for
java -cp . package.sub.Calc
and then having the user type in their problem and hitting enter.
If I have a file named input.txt and want to call it from the command line and have the answers print out in the commandline (program is designed to System.out.println) how would I be entering this information in?
My current code implements a Scanner for System.in. Would I have to use anything else to get this to work? I am new to running anything in the command prompt and can't seem to get it to work.
Any help is greatly appreciated.
My code:
public static void main(String[] args) {
Calc calc = new Calc();
Scanner sc = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
String input = "";
List<String> strs = new ArrayList<>();
ArrayList<String> tokens;
while (sc.hasNextLine()) {
String line = sc.nextLine().trim();
if (line.isEmpty()) {
for (String s : strs) {
sb.append(s);
input = sb.toString();
}
tokens = new ArrayList<>(Arrays.asList(input.split(" ")));
//call calculate and reset
calc.calculate(tokens);
strs.clear();
tokens.clear();
sb.setLength(0);
input = "";
} else if (line.length() == 1) {
strs.add(" ");
strs.add(line);
strs.add(" ");
//manual user exit case
} else if (line.equals("EXIT")){
System.exit(0);
}else {
strs.add(line);
}
}
}

You seem to have 2 problems.
1) You're including the -cp commandline option when you run the program manually, but not when you try and read from the input. You need it in both cases - that's telling java where to find your class file.
2) The way you are handling your input doesn't match the input you're passing in.
You only call calculate when you receive an empty line ( if(line.isEmpty()) ), but something like
echo some inputs to the calculator | java -cp . package.sub.Calc
doesn't ever produce a blank line.
You either need to do:
printf "%s\n\n" "some inputs to the calculator" | java -cp . package.sub.Calc
or change the condition that triggers a calculate (probably by invoking it outside of the while loop).

your input is received in your main method. public static void main (String[] args). The args array is the array which will receive your input parameters IF you have ran your program as java -cp . <main_class_pat> <arg0> <arg1> ...
Make sure your args array has desired length ... and if so, your input file would be at arg[0]

Related

Get the input on the same line java

I have this to ask the user a command but I want the input to be written on the same line the user is asked.
public class Controller{
private Scanner in;
public void run(){
String line;
System.out.print("Command > ");
line = in.next();
}
So I get this:
Command >
help
And I want this:
Command > help
Your IDE is lying to you a bit. The current context that you have written will prompt on the same line when you run the .jar, but IntelliJ breaks the input and output between 2 different lines. Rest assured that your prompt is working properly.

How do I pipe input into a java program, but have that input still show in the output?

Let's say I have a program that asks for three numbers using scanner, something like this:
Scanner console = new Scanner(System.in);
int[] numbers = new int[3];
System.out.println("Hello!");
for (int i = 0; i<3; i++){
System.out.print("Please enter a number: ");
numbers[i] = console.nextInt();
}
I want to test a program like this by redirecting some input to it, and then redirecting the output to a file.
input.txt
3
4
5
command
java program < input.txt > output.txt
The problem is that the output.txt will look something like this
Hello!
Please enter a number: Please enter a number: Please enter a number:
As opposed to something like this
Hello!
Please enter a number: 3
Please enter a number: 4
Please enter a number: 5
Is there any way to make output.txt look more like the second one? I'm on a Mac, if that changes anything.
I do NOT want to modify the code - I have to run this test for a lot of similar programs.
Why your program doesn't work as expected
In your output, the strings "Please enter a number:" are chained without newlines, because you don't print the newlines in the program. When the program is running in interactive mode, the user enters the newlines.
There are no numbers in the output file, because your program doesn't print them to the standard output. Again, when the program is running in interactive mode, the user enters the numbers, but not the program. In the case of redirected output, the numbers coming from the input file are read by the program, but never printed to the standard output.
The correct way
You should check if the program is running in interactive mode (when the input is read from a TTY).
test/MyApp.java
package test;
import java.util.Scanner;
import java.io.Console;
class MyApp {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
Console console = System.console();
int[] numbers = new int[3];
for (int i = 0; i < 3; i++){
if (console != null) {
System.out.print("Please enter a number: ");
}
numbers[i] = scanner.nextInt();
System.out.printf("Number: %d\n", numbers[i]);
}
}
}
Testing
$ printf '%d\n%d\n%d\n' 1 2 3 > file
$ javac -cp . test/MyApp.java
$ java -cp . test/MyApp < file > out
$ cat out
Number: 1
Number: 2
Number: 3
What you may do to have the mixed values for inputs and outputs is :
1) Create your own application, which will call the main method of the application to test (provided all applications have the same package and main class name, or you would have to give this info to your own program, and use reflection to invoke the other program) .
Your application will perform the following steps :
2) Store the regular System InputStream :
InputStream oldInputStream = System.in;
3) Create your own subclass of InputStream (let's call it YourCustomInputStream), and implement the different read methods, to print what was read from System.in to System.out, and also return the value.
e.g :
#Override
public int read(){
int readInt = oldInputStream.read();
System.out.println(readInt);
return readInt;
}
4) Replace the System's input by your own stream :
System.setIn(new YourCustomInputStream());
5) Call the main method of the application to test.
First I wanted to merge stdout and stderr like this:
while read -r num; do
sleep 1
echo ${num}>&2
echo ${num}
done < input.txt | java program
This will fail when you want to redirect the result to a file.
So can you try the next construction:
while read -r num; do
sleep 1
echo ${num}
done < input.txt| tee -a output.txt| java program >> output.txt

Stuck on a Java instruction

Question:
The commands should be passed in to the program as a file with one instruction per line. The English instructions are in the file commands in english.txt and the Spanish instructions are in the file commands in spanish.txt. You call the program by the passing in the instructions as follows:
java ConsoleRobot < commands_in_english.txt
or
java ConsoleRobot < commands_in_spanish.txt
I don't get what the question is asking? Does it want me to have the commands I enter to go to the english text file or does it want me to have all my commands stored in the english text file?
Here is a link to the full question. I got all of it except the last part. Here is a link to my Java file.
import java.util.Scanner;
public class ConsoleRobot extends SmarterRobot {
public static void main(String [] args) {
World yard = new World();
SmarterRobot ringo = new SmarterRobot();
yard.add(ringo,5,4);
yard.addBeeper(5,9);
yard.addBeeper(4,5);
yard.addBeeper(9,4);
yard.addBeeper(9,5);
Scanner scan = new Scanner(System.in);
System.out.println("Enter a command: | Introduzca un comando:");
String command = scan.nextLine();
command = command.toLowerCase();
while (!command.equals("stop") && !command.equals("detener")) {
if ( command.equals("forward") || command.equals("adelante")) {
System.out.println("How far should the robot move?");
int input = scan.nextInt();
ringo.moveNumOfTimes(input);
} else if ( command.equals("right") || command.equals("derecha"))
ringo.turnRight();
else if ( command.equals("left") || command.equals("izquierda")
ringo.turnLeft();
else if ( command.equals("collect") || command.equals("recoger"))
ringo.pickBeeper();
else if ( command.equals("drop") || command.equals("soltar"))
ringo.putBeeper();
System.out.println("Enter a command: | Introduzca un comando:");
command = scan.nextLine();
}
System.out.println("Finished | Terminado");
}
}
You don't need to do any code to accept the file passed with the < operator. As Majora320 wrote, the < operator renders the file to the standard input. In other wrods, your application will read the commands from the file as if it would have been entered from the keyboard.
The problem is with the scan.nextLine() call. This reads a whole line, and that makes impossible processing commands with parameter, e.g. forward 10 since you read in the whole line, not only the command.
The example below reads first a string (in.next()), and may continue with reading the parameter (in.nextInt()) if a command is expected to have a parameter. But it does not read any parameters for the stop command.
public class Robot {
public static void main(final String[] args) {
final Scanner in = new Scanner(System.in);
while (in.hasNext()) {
final String command=in.next();
if (command.equals("forward")) {
final int distance=in.nextInt();
System.out.println("Forwarding "+distance);
}
if (command.equals("stop")) {
System.out.println("Stopping");
}
}
}
}
The other little problem is that you're keep on reading the input until getting a stop command. This means that command files with no ending stop will not stop your application. It is safer to read until there is something to read, i.e. use while (in.hasNext()) to keep on reading.
Note how indentation and empty lines makes the code more readable, and much easier to follow.
The < operator (At least on the *nix terminal) is for passing the text from a file into the stranded input of a program. For example, grep "hello" < myfile.txt is exactly the same as cat myfile.txt | grep "hello". Basically, < is an abbreviation for running cat file | command. So what java ConsoleRobot < commands_in_english.txt means is pass all the lines in commands_in_english.txt to the stranded input of the ConsoleRobot program. That means you just write the instructions to the file and then run the command.

How to send a filename through batch & accept it in Java

Ok so I might have worded this wrong, it's a little difficult to explain. So here goes:
Main Goal: Call java triangle program through batch while also piping a list of testcase.txt files with input that must be sent to the java program to determine the triangle type. WITHOUT hard typing the file name into the java program.
Problem:Not sure how to accept the fileName to use in the java application from the batch command window.
Currently, I'm just using one text file to test with containing 3 numbers separated by a space. When running the java program by itself I can type the file path to the text file & everything works as intended. But alas I can't hard code or ask the user for that path since this should be setup by the batch file to call these 15 test case files to send to the program. The part of code I have now that I dont understand is this:
Scanner input = new Scanner(System.in);
String fileName = input.next();
Scanner reader = new Scanner (new File(fileName));
So I understand that input.next() is going to be asking for keyboard input how can I switch this from keyboard input to batch file input? If that makes sense.
Here is my batch file:
#ECHO off
set /P num1="Please enter file path: "
echo You entered %num1%
ECHO Checking for file...
if exist %num1% (
set num1=Congrats! I found the file!
C:\Users\josh\Documents\NetBeansProjects\Triangle\src\TriangleRebuild.java
) else (set num1=File does not exist)
echo %num1%
PAUSE
exit
Full Code:
/*
* Josh
Software Engineering
Structured Triangle Implementation in Java
*/
import java.io.*;
import java.util.*;
public class TriangleRebuild {
public static void main(String[] args) throws FileNotFoundException{
Scanner input = new Scanner(System.in);
String fileName = input.next();
Scanner reader = new Scanner (new File(fileName));
int a;
int b;
int c;
boolean isATriangle;
System.out.println("Enter 3 integers which are sides of a triangle: ");
a = reader.nextInt();
b = reader.nextInt();
c = reader.nextInt();
System.out.println("Side A is: " + a);
System.out.println("Side B is: " + b);
System.out.println("Side C is: " + c);
if((a < b + c) && (b < a + c) && (c < a + b)){
isATriangle = true;
}
else{
isATriangle = false;
}
if(isATriangle){
if((a == b) && (b == c)){
System.out.println("Triangle is Equilateral.");
}
else if((a != b) && (a != c) && (b != c)){
System.out.println("Triangle is Scalene.");
}
else{
System.out.println("Triangle is Isosceles.");
}
}
else{
System.out.println("Not a Triangle.");
}
if((Math.pow(c,2) == Math.pow(a,2) + Math.pow(b,2))){
System.out.println("Triangle is a right Triangle.");
}
else{
System.out.println("Triangle is not a right Triangle.");
}
}
}
You know that every main method is declared like this:
public static void main(String[] args) {...}
That args array represents command line arguments. That is, parameters you wrote on the java command line in your cmd window or your batch. So for example, if you have a line in your batch that says:
java TriangleRebuild abc.txt
Then inside the program, the array args will have the value { "abc.txt" }. You can access that by using args[0]. You have to make sure, of course, that args.length > 0 and that args[0] != null before you use it, just in case someone forgot to write the file name on the command line.
You can pass several file names in the command line.
java TriangleRebuild abc.txt def.txt hij.txt
And then your array will be: {"abc.txt","def.txt","hij.txt"} inside the program.
This way, you can pass argument from your batch to your Java and process them without interaction with the user.
Your best bet will likely be as follows: have the Batch file pipe the text file locations, as if they were input in a command line. Then, use those command line arguments to call the main method of your java class (simply invoke it like you would from the command line, with all of your batch input as the Args). Once inside the main method, do with them as you wish.

Trouble With hasNext() in Java

I'm trying to write a program that reads pairs of words and outputs the number of pairs of identical words. It's assumed an even number of words are inputted. When I run my code, it doesn't output anything. It appears to be continually running. When I press Ctrl-Z after I'm done inputting words, it either returns "0" or nothing at all. Any thoughts on how to make my program run properly? Thanks.
EDIT: it runs fine in the command prompt, but not in Eclipse.
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int counter = 0;
while (input.hasNext()) {
String string1, string2;
string1 = input.next();
string2 = input.next();
if (string1.equals(string2)) {
++counter;
}
}
System.out.println(counter);
}
You are asking hasNext() once, but then calling next() twice. The second next() can fail if there are no more elements.
It doesn't really work in eclipse for me (nor does in netbeans for what i have read), to test if your code actually works well you should do this:
(In windows) Open a command prompt ( execute ... "cmd" + Enter )
then compile your class or classes with
javac YourClass.java
if no errores it will just let you type a new command with no messages and then
java YourClass
then you can try the Ctrl + z in windows (ctrl + d in linux) which will print the ^Z character and then hit enter.
Hope it helped.

Categories

Resources