Java and stdin vs a file - java

I have to do this assignment but the thing says "All the programs should take input from STANDARD INPUT, not from a file." , this is fine to ask advice on, but what does this mean?
I was doing the code below but then someone said this is not correct, that its as if someone typed on the cmdline not a redirection from a file. I'm confused here, how do I do this so its stops when whoever tests my code gives it data, of while I don't know how they will other than stdin? Thanks, the data gets rather large like 500k.
List<Double> list = new ArrayList<Double>();
/*
* Get the data from the stdin and read into a buffer until its done.
*/
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String s;
try {
while ((s = in.readLine()) != null && s.length() != 0) {
double myReal = Double.parseDouble(s);
// System.out.println(myReal);
list.add(myReal);
// System.out.println(s);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Related

Trying to read multiple lines of cmd input

I'm trying to write a method that:
Prints out a message (Something like: "Paste your input: ")
Waits that the user presses enter.
Reads all the lines, that got pasted and adds them up in one String.
(An empty line can be used to determine the end of the input.)
The first syso does the printing part and also the first line gets read correctly, but then it never exits the while loop. Why? There has to be an end?
public static String readInput(String msg) {
System.out.print(msg);
String res = "";
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in))) {
String line;
while ((line = buffer.readLine()) != null && !line.isBlank())
res += "\n" + line;
} catch (IOException e) {
e.printStackTrace();
}
return res;
}
Ive already seen the following sites, but they all didn't help:
How to read input with multiple lines in Java
https://www.techiedelight.com/read-multi-line-input-console-java/
Make the console wait for a user input to close
Edit:
The same bug applies for:
public static String readInput(String msg) {
System.out.print(msg);
String res = "";
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in))) {
res = buffer.lines().reduce("", (r, l) -> r + "\n" + l);
System.out.println(res);
} catch (IOException e) {
e.printStackTrace();
}
return res;
}
Edit 2:
I've tried this code in my actual project and in a new test-project, but with different results. Here is a video of that test.
Why wouldn't use this statement?
while (!(line = buffer.readLine()).isEmpty())
In this case sending empty line will exit the loop.
Although, if you insert large text with empty lines (for example, the beginning of a new paragraph, or a space between them) will terminate the program.

JAVA - Sending data to child process in a loop

I want to send some string to a child process and them, and this send me back in uppercase. The idea is that i put an empty string,both process will stop.
The first time works all great but the next times the process get stuck in the second time and i need to force close.
Father Code ->
public class padre {
public static void main(String[] args){
System.out.println("Soy el padre");
try {
Process p = Runtime.getRuntime().exec("java -jar C:\\Users\\Cristian\\Desktop\\hijo.jar");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader escritorPadre = new BufferedReader(isr);
//Leer del hijo
BufferedReader brHijo = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader brHijoError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//EScribir en el hijo
OutputStream os = p.getOutputStream();
String lineaConsola;
while((lineaConsola = escritorPadre.readLine()).isEmpty() == false){
lineaConsola +="\n";
os.write(lineaConsola.getBytes());
os.flush();
String linea;
while((linea = brHijo.readLine()) != null){
System.out.println(linea);
System.out.println("Atascado en el while del padre");
}
while((linea = brHijoError.readLine()) != null){
System.out.println(linea);
System.out.println("Atascado en el while del padre error");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Child code ->
public class hijo {
public static void main(String[] args){
InputStreamReader in = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(in);
String linea;
try {
while(!(linea = br.readLine()).isEmpty()){
System.out.println("Hijo -> " + linea.toUpperCase()+"\n");
System.out.println("Atascado en el while del hijo");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
You have several problems here.
First, in your main loops (both father and son), you are not checking for end-of-file. This means that you can get null from the stream reader, and you'll get a NullPointerException when you try to access isEmpty().
Second, you are never passing an empty line to the son process, because as soon as the line you get from escritorPadre.readLine() is empty, you get out of the while loop. So the son checking for isEmpty() is futile. It would be better to close the stream to the son as soon as you exit (you always have to close streams when you finish with them, anyway), and handle the null on the son side.
But most importantly: your loop for reading from the son will always get stuck, because you will only get null from the son side on end-of-stream. And you will only get end-of-stream if the son uses close() on its output stream (or the son terminates). But if you did use close() on the son side, you'll not be able to write to standard output again.
So your loop just keeps waiting for the son to write something else, and the son is waiting for the father to write something else before it writes something. So the process is in a deadlock.
You could decide that the son should send some special output (an empty line) so you know when to stop reading its output.
But then you have a problem with standard error. After you finish reading from the son's output, you start reading from standard error. So to allow you to leave that loop, you'll also have to print an empty line to standard error after each write to the output, and also add an empty line to the stack trace being printed from every catch. Then you'll also have to add a check for empty line in the father's loop reading the son's standard error.
Personally, I think that's not very elegant. But it's doable.
Anyway, to get you started, on the father side you should make sure you close all the streams and check for null on reading. Something like:
try {
p = Runtime.getRuntime().exec("java -jar C:\\Users\\Cristian\\Desktop\\hijo.jar");
} catch ( IOException e ) {
e.printStackTrace();
return;
}
// Use try-with-resources to open all the streams and readers
// so that they will be closed automatically
try (
BufferedReader escritorPadre = new BufferedReader(new InputStreamReader(System.in));
//Leer del hijo
BufferedReader brHijo = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader brHijoError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//EScribir en el hijo
OutputStream os = p.getOutputStream();
) {
String lineaConsola;
// Read until either end-of-file or empty line
while((lineaConsola = escritorPadre.readLine()) != null && ! lineaConsola.isEmpty()){
... // I ommitted the reading from the son until you decide how you want to arrange it.
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
And in the son, also, make sure to close all the resources or use try-with-resources, and check for both null and empty line:
try (
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
){
while((linea = br.readLine()) != null && ! linea.isEmpty()){
System.out.println("Hijo -> " + linea.toUpperCase()+"\n");
System.out.println("Atascado en el while del hijo");
// Decide how you want to handle telling the father that output is done
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

How to stop a NullPointerException when using BufferedReader (readLine()) to check for any more values

I have written some code to read in Vehicle data from a .txt file. At the moment I can read in all the data correctly and create the objects fine. I have a while loop that checks for the text "Vehicle Details" in the file and if it is present (i.e. there is another vehicle to add) it enters the loop to add the data.
The problem is that when there isn't anymore data the readLine() method is still called and this creates a NullPointerException (at least that's what I think is the cause)
Here is the method in use.
public static void addNewVehicleFromFile(Showroom s)
{
try
{
FileInputStream fStream = new FileInputStream("AddVehicleFromFile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fStream));
String stringLine;
while ((stringLine = br.readLine()).equalsIgnoreCase("Vehicle Details"))
{
System.out.println("P1");//Testing
br.readLine();
String[] manufacturer = br.readLine().split(" =");
String[] model = br.readLine().split(" =");
String[] vin = br.readLine().split(" =");
String[] dateOfMan = br.readLine().split(" =");
String[] taxBand = br.readLine().split(" =");
String[] cost = br.readLine().split(" =");
System.out.println("P2");//Testing
System.out.println(manufacturer[0].toString());
System.out.println(model[0].toString());
System.out.println(vin[0].toString());
System.out.println(dateOfMan[0].toString());
System.out.println(taxBand[0].toString());
br.readLine();
System.out.println("P3");//Testing
int strToInt = Integer.parseInt(cost[0]);
Vehicle inputVehicle = new Vehicle(manufacturer[0], model[0], vin[0], dateOfMan[0],
taxBand[0].charAt(0), strToInt);
System.out.println("P4");//Testing
s.addVehicle(inputVehicle);
System.out.println("P5");//Testing
}
}
catch (FileNotFoundException fnfe)
{
System.out.println("File not found exception: " + fnfe.toString());
}
catch (IOException ioe)
{
System.out.println("I/O exception: " + ioe.toString());
}
System.out.println("addNewVehicleFromFile Complete");
}
Not sure if you need it but here is my file data.
Vehicle Details
Fordtest =manufacturer
Focus =model
ioCheck =VIN
09/01/1989 =DateOfMan
d =TaxBand
19900 =Cost
Vehicle Details
Fordtest2 =manufacturer
Focus2 =model
ioCheckVIN2 =VIN
09/01/1989 =DateOfMan
a =TaxBand
1922 =Cost
Finally, to make it clear where the program runs to I have added in some console output as testing. The while loops iterates twice outputting p1-p5 both times before the error occurs and it never reaches the final console output saying the method is complete.
Check that the result of calling readLine() is not null (empty). If you check, and cause it not to do anything if its empty, this will solve your issue!
Try checking if readLine() is null.
while ((stringLine = br.readLine()) != null) { }
This will make sure that there is something in that line to read, else it has reached end of file.
In your code you have 3 calls to readLine() each iteration. This could cause issues if for some reason the formatting in your text file is changed(missing a blank line for example). You may be better off making each vehicle on one line, seperated by commas. For example:
Vehicle Details
Fordtest =manufacturer
Focus =model
ioCheck =VIN
09/01/1989 =DateOfMan
d =TaxBand
19900 =Cost
Vehicle Details
Fordtest2 =manufacturer
Focus2 =model
ioCheckVIN2 =VIN
09/01/1989 =DateOfMan
a =TaxBand
1922 =Cost
Then becomes:
Fordtest, Focus, ioCheck, 09/01/1989, d, 19900
Fordtest2, Focus2, ioCheckVIN2, 09/01/1989, a, 1922
This would simplify the code somewhat, as well as reducing chance for error.
Also make sure to close the FileInputStream when you are finished with it. This insures that any resources associated with it are released properly.
try {
FileInputStream fStream = new FileInputStream("AddVehicleFromFile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fStream));
...
} finally {
try {
if (fStream != null) {
fStream.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}

calling a perl script from a java code in a interactive way

Can someone help me in the below scenario,
I need to call a perl script from my java code. The perl script is an interactive code, which gets the input from the user during its execution and continues further to end. So, the example I have used is, the perl script when executed asks for the age by printing in the console "How old are you?", when the user enter some value say '26'. Then it prints "WOW! You are 26 years old!".
When I tried calling this script from my java code, the process waits till I give the value as 26 in the outputstream, while in the inputstream there is no value. Then finally when again I read the inputstream, i get the entire output of the script together. So, here can't I make it interactive?
I have went through many forums and blogs, but couldn't locate any, which exactly target my requirement.
Here is the java code
import java.io.*;
public class InvokePerlScript {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Process process;
try
{
process = Runtime.getRuntime().exec("cmd /c perl D:\\sudarsan\\eclips~1\\FirstProject\\Command.pl");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
out.write("23");
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
process.waitFor();
if(process.exitValue() == 0)
{
System.out.println("Command Successful");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
else
{
System.out.println("Command Failure");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
catch(Exception e)
{
System.out.println("Exception: "+ e.toString());
}
}
}
Perl code is as below
$| = 1;
print "How old are you? \n";
$age = <>;
print "WOW! You are $age years old!";
Thanks in advance,
Sudarsan
Are you calling flush() on the OutputStream in Java after writing the values? If you don't, there's a good chance they'll just be held in the stream's buffer within the Java process, and so never make it to Perl (with the result that both processes end up waiting for the other's IO.)
(Depending on the implementation of the stream this may or may not be necessary, but it certainly wouldn't hurt - and I've been bitten by this in the past. Usually one doesn't need to be as careful, since flushing happens implicitly when close() is called, but here you can't close the stream after you've finished writing.)
It looks like you're trying to read a full line in this code:
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
...
However, in your perl code, you are not printing an endline character, so readLine never returns (as per the documentation).

Command Line Pipe Input in Java

Here is a simple piece of code:
import java.io.*;
public class Read {
public static void main(String[] args) {
BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
String x = null;
try{
x = f.readLine();
}
catch (IOException e) {e.printStackTrace();}
System.out.println(x);
}
}
}
I execute this as : java Read < input.txt
Once the input.txt is completely piped into the program, x keeps getting infinite nulls. Why is that so? Is there a way by which I can make the Standard In(Command Line) active after the file being fed into the code is done?
I've tried closing the stream and reopening, it doesn't work. Reset etc also.
By executing "java Read < input.txt" you've told the operating system that for this process, the piped file is standard in. You can't then switch back to the command line from inside the application.
If you want to do that, then pass input.txt as a file name parameter to the application, open/read/close the file yourself from inside the application, then read from standard input to get stuff from the command line.
Well, this is typical for reading in a BufferedReader. readLine() returns null when end of stream is hit. Perhaps your infinite loop is the problem ;-)
// try / catch ommitted
String x = null;
while( (x = f.readLine()) != null )
{
System.out.println(x);
}
You need to terminate your while loop when the line is null, like this:
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
catch (IOException e) {
logger.error("IOException reading System.in", e);
throw e;
}
finally {
if (in != null) {
in.close();
}
}
Is there a way by which I can make the Standard In(Command Line)
active after the file being fed into the code is done?
Sorry to bump an old question, but none of the answers so far points out that there is a (shell-only) way to pass back to console input after piping in a file.
If you run the command
{ cat input.txt & cat; } | java Read
then the text from input.txt will be passed to java Read and you will then be dropped back to console input.
Note that if you then press Ctrl+D, you will get the infinite loop of nulls, unless you modify your program to end the loop when it receives null.

Categories

Resources