BufferedReader not seeing end-of-file on StdIn when run under Eclipse - java

I'm reading standard input:
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
var line = br.readLine();
if (line == null) break;
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
System.err.println("Done.");
}
If I use this in a terminal:
java TheClass </path/to/file
... it works: the program runs to completion.
But under Eclipse, if I set the same file as standard input (Run Configurations>Common>Standard Input and output), the program reads the file but it hangs after the last line until I enter a Ctrl-D in the console window (and then terminates normally).
Also under Eclipse, if I use the file directly (FileInputStream) the file is read to the end and the program terminates immediately.
Am I missing something or is this an Eclipse problem?
Using Eclipse 2020-06 on Linux with openjdk 11.

Sounds like Eclipse bug: 513713 - In Run configuration when reading standard input from file, EOF is not issued at the end

Related

InputStreamReader throws NullPointerException when launching via cmd

I wrote some code to open and read the content of a csv file:
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream(fileName)));
String line;
try {
line = bufferedReader.readLine();
while (line != null) {
line = bufferedReader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// close buffered reader
}
The code is working fine in unit tests, no exception is raised. However once I try to launch the program via cmd it throws a NPE coming from InputStreamReader:
Exception in thread "main" java.lang.NullPointerException
at exercise.FileLoader.loader(FileLoader.java:28)
at exercise.Application.main(Application.java:22)
The program takes actually the file name as parameter:
public static void main(String[] args) {
if (args.length > 1) {
System.out.println("Too many input arguments.");
System.exit(-1);
}
String fileName = args[0];
//here runs the method who reads the csv file above
}
Could you tell me what is happening ?
The following reads not a File on the file system, but a resource on the class path (principly read-only).
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(getClass().getResourceAsStream(fileName)));
Also the encoding is that of current platform, which might differ on another PC.
And I see no close() which probably got deleted on preparing the question.
For the file system:
Path path = Paths.get(filename);
try (BufferedReader bufferedReader =
Files.newBufferedReader(path, Charset.defaultCharset())) {
line = ...
...
} // Automatic close.
There has to be taken some care when the path is not absolute. Then it depends where the "working directory" points to, where the application is started.
I think your problem is related to the program being unable to find the file once you launch the program via cmd.
Have you tried putting the program in the same folder of the file? You could also ask for a user's input in the main so that you can provide the correct folder.

running multiple cmd commands through java separated by some another code

I want to start a cmd command, then after the first command is done, I want to run a code to adjust some text in a file, then execute another command on the same cmd window. I don't know how to do that and everywhere I looked the answer is for the commands after each other which is not this case. the code for editing the text works fine without starting the cmd but if I execute the cmd command it does not change. code below.
public static void main(String[] args)throws IOException
{
try
{
Main m1 = new Main();
Process p= Runtime.getRuntime().exec("cmd /c start C:/TERRIERS/terrier/bin/trec_setup.bat");
p.waitFor();
/*code to change the text*/
m1.answerFile(1);
m1.questionFile(1);
/**********************/
//code to add another command here (SAME WINDOW!)
/************************/
}
catch(IOException ex){
}
catch(InterruptedException ex){
}
Execute cmd and send your command lines (.bat) to the standard input.
Process p = Runtime.getRuntime().exec("cmd");
new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null)
System.out.println(line);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
try (PrintStream out = new PrintStream(p.getOutputStream())) {
out.println("C:/TERRIERS/terrier/bin/trec_setup.bat");
out.println("another.bat");
// .....
}
p.waitFor();
For starters, the \C option terminates CMD after executing the initial command. Use \K instead.
You won't be able to use waitFor() to detect when the initial command is done, because if you wait until the CMD terminates, you won't be able to re-use the same process.
Instead, you'll need to read the output of CMD process to detect when the batch file is complete and you are prompted for another command. Then write the next command line that you want to execute though the input stream of the Process.
Sounds like a pain. Why would do you need to use the same window?

Output is incomplete when running jdb as a process from java application

I'm trying to debug a java class from java program. I created a simple class to test. This is my class hello.java and it lies in the folder C:\Users\madhawax\Desktop\beaufify\debugging
My problem is that I can't retrieve the part
VM Started: Set deferred breakpoint Hello.main
...
when I run jdb from java code, but when I manually run jdb from command line I can see it.
Why do I get only part of the real output? How can I fix this?
This is my Hello.java class:
public class Hello {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println("loop number "+i);
}
}
}
I used 3 commands to run jdb
jdb
stop in Hello.main
run Hello
Console output when I debug manually using cmd .
C:\Users\madhawax\Desktop\beaufify\debugging>jdb
Initializing jdb ...
> stop in Hello.main
Deferring breakpoint Hello.main.
It will be set after the class is loaded.
> run Hello
run Hello
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
>
VM Started: Set deferred breakpoint Hello.main
Breakpoint hit: "thread=main", Hello.main(), line=3 bci=0
3 for (int i = 0; i < 10; i++) {
main[1]
Output when I run jdb using java code .
run:
Initializing jdb ...
> Deferring breakpoint Hello.main.
It will be set after the class is loaded.
> run Hello
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
> Input stream closed.
BUILD STOPPED (total time: 4 seconds)
I used this code to run jdb.
try {
ProcessBuilder builder = new ProcessBuilder("C:\\Program Files\\Java\\jdk1.8.0_31\\bin\\jdb.exe");
builder.directory(new File("C:\\Users\\madhawax\\Desktop\\beaufify\\debugging\\"));
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin))) {
writer.write("stop in Hello.main\n");
writer.flush();
writer.write("run Hello");
writer.flush();
}
String inputLine;
Scanner scanner = new Scanner(stdout);
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
} catch (IOException ex) {
ex.printStackTrace();
}
I suggest you to run your code without try-with-resources:
Scanner scanner = new Scanner(stdout);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
writer.write("stop in Hello.main\n");
writer.flush();
writer.write("run Hello\n");
writer.flush();
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
In your code try-with-resources will close BufferedWriter after execution:
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin))) {
writer.write("stop in Hello.main\n");
writer.flush();
writer.write("run Hello");
writer.flush();
} //writer is closed here
Thus, it will close underlying process output stream and this, apparently, leads to closure of jdb process.
You might want to change try-with-resource to try-catch-finally wrapping the whole method.
UPDATE: Also, it's a good idea to read output of one command before running next command. With your approach:
writer.write("stop in Hello.main\n");
writer.flush();
writer.write("run Hello\n");
writer.flush();
writer.write("list\n");
...
There's no pause between command calls. jdb might not be able to handle list command at the time (because it's launching VM). As an experiment you can introduce a time gap:
writer.flush();
Thread.sleep(1000);
writer.write("list\n");
The superior approach is to read output in between.
writer.flush();
readOutput(stdout);
writer.write("list\n");
You can use scanner to read the output. But, as #vandale pointed out in question comments, Scanner blocks on token and line breaks. You might want to use non-blocking reads to read available output. Something like this might work:
private void readOutput(InputStream outputStream) throws IOException{
byte[] buffer = new byte[100000];
int bytesRead;
while (outputStream.available() > 0) {
bytesRead = outputStream.read(buffer);
if (bytesRead > 0) {
System.out.print(new String(buffer, 0, bytesRead));
}
}
}
This code will also show output that doesn't end with a line break (input prompts, main[1], etc.)

Java program using ProcessBuilder with input and output streams doesn't work

I have searched through similar questions here on Stack Overflow, however, I can't seem to make this work.
I have a java program that must use ProcessBuilder to load a C executable file. The file just accepts a string through the CLI and converts it to upper case. The java program creates a system process with ProcessBuilder to manage this executable, and must send the string and receive the converted one to print it in the CLI.
This is the code for uppercases.c:
#include <stdio.h>
int main(int argc, char *argv[]) {
char text[1024];
scanf("%s", &text[0]);
int i;
for(i = 0; i < strlen(text); i++) {
text[i] = toupper(text[i]);
}
printf("%s\n", text);
return 0;
}
I compiled it using
$ gcc uppercases.c -o uppercases
And ran it with
$ ./uppercases
Everything works fine. Now this is the code for Uppercase.java. I have to create an OutputStream to send the string to the C executable (uppercases), and then I create an InputStream to save its output and print it to the CLI:
public class Uppercase {
public static void main(String[] command) {
String textIn, textOut;
Scanner reader = new Scanner(System.in);
// This is what we want to send
System.out.println("Write something: ");
textIn = reader.nextLine();
try {
// Here I create a process to handle "uppercases"
Process process = new ProcessBuilder(command).start();
OutputStream os = process.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
// According to me, this will send the string to "uppercases"
bw.write(textIn);
bw.flush();
// This is to read the output of "uppercases"
InputStream is = process.getInputStream();
BufferedReader br = new BufferedReader (new InputStreamReader(is));
while ((textOut = br.readLine()) != null) {
System.out.println(textOut);
}
os.close();
is.close();
} catch (IOException e) {
System.out.println("I/O error:" + e.getMessage());
} catch (Exception e) {
System.out.println("Error:" + e.getMessage());
}
}
}
To compile, I type:
$ javac Uppercase.java
And to execute:
$ java Uppercase ./uppercases
The problem is that when I type a string and hit enter, the cursor stays forever there, I hit enter again and nothing happens, and finally I have to press CTRL+C to exit. Any help will be appreciated.
All works fine with your java program with one exception : you use a BufferedWriter that you correctly flush, but as the line that you write does not contain a newline, the C program still waits for more input.
If you write :
// According to me, this will send the string to "uppercases"
bw.write(textIn);
bw.write("\n");
bw.flush();
It is enough and the program terminates normally.
But if you really want the things to be bullet proof, you should close bw to clearly indicate to the subprocess that is should not wait for more input :
// According to me, this will send the string to "uppercases"
bw.write(textIn);
bw.close();
Then the program terminates normally (and correctly) even without the end new line. Of course in that case the last os.close() is no longer necessary but is still harmless.

Not getting any output after calling C executable file from Java code

I am trying to execute the C code from Java code which is already compiled and executed, but, I am not getting any output from the executable file. Can anyone help me to complete this task?
Code is as follows.
public class Test {
public static void main(String args[]) {
try {
Process processCompile = Runtime.getRuntime().exec("e:/Sample.exe");
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
Try this:
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(processCompile .getInputStream()));
// read the output from the command
System.out.println("EXE OUTPUT");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
This method would work only if you run the java program with admin privileges.
If you have privileges, then can you try running your process under "cmd" shell (Which is forked by your java process). An implementation do so this is done here "LinuxInteractor" ( But is in linux). Just minor change needed to port to Windows version.
Finding hard and soft open file limits from within jvm in linux (ulimit -n and ulimit -Hn)

Categories