How to check the coming output from main method? - java

For example, with the following main method.
public class Solution {
public static void main(String []argv) {
System.out.println("Hello World.");
System.out.println("Hello Java.");
}
}
I want to know how code a platform (Hackerrank, for example) would check that the main method prints the expected output.
Hello World.
Hello Java.
Is not easy imagine how to do it with Junit, at first sight.
I believe that an external program is checking the output, I mean something like this:
$ java Solution | runtests
Thank you

Your guess using unix pipe-lining is certainly a way that it could be done.
In Java, you could do it by running the java command and reading the output through an InputStream
// Create and start the process
Process pb = new ProcessBuilder("java", "Solution").start();
// Create a reader to read in each output line
BufferedReader reader = new BufferedReader(new InputStreamReader(pb.getInputStream()));
String line;
// Read in line by line
while((line = reader.readLine()) != null) {
// ...
}
Note that the start() method of ProcessBuilder can throw an IOException, so you will need to account for that.

Related

Issue in calling Python code from Java (without using jython)

I found this as one of the ways to run (using exec() method) python script from java. I have one simple print statement in python file. However, my program is doing nothing when I run it. It neither prints the statement written in python file nor throws an exception. The program just terminates doing nothing:
Process p = Runtime.getRuntime().exec("C:\\Python\\Python36-32\\python.exe C:\\test2.py");
Even this is not creating the output file:
Process p = Runtime.getRuntime().exec("C:\\Python\\Python36-32\\python.exe C:\\test2.py output.txt 2>&1");
What is the issue?
I think you could try your luck with the ProcessBuilder class.
If I read the Oracle documentation correctly, the std inputs and outputs are directed to pipes by default but the ProcessBuilder has an easy method for you to explicitly set output (or input) to a file on your system or something else.
If you want your Python program to use the same output as your Java program (likely stdout and stderr), you can use stg like this:
ProcessBuilder pb = new ProcessBuilder("C:\\Python\\Python36-32\\python.exe", "C:\\test2.py");
pb.redirectOutput(Redirect.INHERIT);
Process p = pb.start();
You can use the ProcessBuilder API, redirecting the output to a file and then wait for the result.
public class Main {
public static final String PYTHON_PATH = "D:\\Anaconda3\\python.exe";
public static final String PATH_TO_SCRIPT = "D:\\projects\\StartScript\\test.py";
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder();
builder.command(PYTHON_PATH, PATH_TO_SCRIPT);
// Redirect output to a file
builder.redirectOutput(new File("output.txt"));
builder.start().waitFor();
// Print output to console
ProcessBuilder.Redirect output = builder.redirectOutput();
File outputFile = output.file();
BufferedReader br = new BufferedReader(new FileReader(outputFile));
String st;
while ((st = br.readLine()) != null) {
System.out.println(st);
}
}
}
The python file test.py contains a simple print statement:
print("Hello from python")
I guess it would be even simpler, if you do not need to wait for the result.
Using the Process API should work, too.
Like in your example (I am using the same constants declared above):
Process p = Runtime.getRuntime().exec(PYTHON_PATH + " " + PATH_TO_SCRIPT);
p.waitFor();
byte[] buffer = new byte[1024];
byte[] errBuffer = new byte[1024];
p.getInputStream().read(buffer);
p.getErrorStream().read(errBuffer);
System.out.println(new String(buffer));
System.out.println(new String(errBuffer));
To see the output of the print statement, you need to wait and redirect the streams. Same for the error stream.
Now if you break the python script like this:
print("Hello from python')
you should be able to see the error printed as well.
One way to start a python process is using an entrypoint - test.cmd
echo Hello
python hello.py
here is hello.py
#!/usr/bin/env python3
import os
if not os.path.exists('dir'):
os.makedirs('dir')
Here is my Java code:
public static void main(String[] args) throws IOException {
try {
Process p = Runtime.getRuntime().exec("test.cmd");
p.waitFor();
Scanner sc = new Scanner(p.getInputStream());
while(sc.hasNextLine()){
System.out.println(sc.nextLine());
}
sc.close();
} catch (Exception err) {
err.printStackTrace();
}
}

Java exec. Is it possible to get force flush?

I am new in java, so my question can be muddled.
I tried to run some process from java. It is xmr-stack miner. I use code like that:
package com.company;
import java.io.*;
public class Main {
public static void main(String[] argv) throws Exception {
try {
String line;
Process p = Runtime.getRuntime().exec( "D:\\xmr-stak.exe " +
/* some arguments */ );
BufferedReader in = new BufferedReader(
new InputStreamReader(p.getInputStream()) );
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
}
catch (Exception e) {
// ...
}
}
}
It works perfect for common things.
But I faced an issue that I have no output after some point in xmr-stak. As far as I understand at some point this app create child process. And I didn't see output produced by this child process.
But after very long time working (10+ minutes) I got my output for all this time.
It is looks like some output buffer was flashed after overflow.
Now I want to understand how to get required output more often in java.
From other side I wrote same logic in c++
(Based on this question SO arswer)
And I got my output in time.
Runtime.exec is obsolete. You can replace your entire program with a few lines that use ProcessBuilder:
ProcessBuilder builder = new ProcessBuilder("D:\\xml-stak.exe",
arg1, arg2, arg3);
builder.inheritIO();
Process p = builder.start();
p.waitFor();
You don’t need to read the process’s output (and therefore don’t have to worry about buffering), because inheritIO() makes that output appear in your Java program’s output.
You also don’t need to catch any exceptions, since your main method already has throws Exception.

How to execute "less" with paging from a Java console application?

I need to execute the less command, with paging, from my Java console application. However, the only method I found to execute external commands is Runtime.getRuntime().exec(), which requires me to write/read input/output via streams. So commands like cat work (and less does in fact act like cat), but I need the paging functionality.
In C, I'd use system(). In Ruby, Kernel.exec does the job.
Is there any way to get this done in Java?
When you execute an external process with Runtime.exec() its standard input and output streams are not connected to the terminal from which you are running the Java program. You can use shell redirection to connect it, but first you need to know what terminal to use. There is no way to find the terminal using the standard API but probably you can find an open source library that does it.
To see that it can be done, this program opens itself in less:
public class Test {
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec(
new String[] {"sh", "-c",
"less Test.java < "+args[0] + " > "+args[0]});
System.out.println("=> "+p.waitFor());
}
}
To run it you should use java Test $(tty). The tty program prints the name of the terminal connected to its stdin.
I'm not too sure about the portability of this solution; at least it works on Linux.
List item
The following program will work, initially it prints 10 lines , then press enter it will print next line till end of the file.
run program like
java Less $fileName
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class Less
{
public static void main(String args[]) throws IOException
{
FileReader reader = new FileReader(args[0]);
BufferedReader buff = new BufferedReader(reader);
String readLine;
int lineCount = 0;
while ((readLine = buff.readLine()) != null)
{
System.out.println(readLine);
lineCount++;
if (lineCount > 10)
{
Scanner scanner = new Scanner(System.in);
scanner.nextLine();
}
}
}
}

How to run command line within java using thread async

I am new to java. I am tasked to write java program to run the command lines. I tested the command line under the DOS prompt since i do not have have access to Linux box yet. it worked fine. See the PROGRAM below for full command line syntax. the job will take 6 input files and generate some output files. Next i tried to create a class to and using getruntime and process to process this job. Even it compiled without error but when i run it just show the cursor blinking... i thought i need to use Thread async technique. please provide some advices since i do not have enough time for the projects. I also would like to implement a call back or return values when the job is done. an example would be greatly appreciated. Thanks
import java.io.*;
public class RunJob {
// public static final String PROGRAM = "c:\\wrk\\java.exe Hello";
//one command line below
public static final String PROGRAM = "c:/java.exe -cp \"wrk/jmp.jar;wrk/colt.jar\" gov.lanl.yadas.reliability.UltimateMissileReliabilityModel 10000 \"wrk/\" x1.dat x2c.dat x3.dat x4.dat x5.dat x6.dat true";
// Set to true to end the loop
static boolean done = false;
public static void main(String argv[]) throws IOException {
BufferedReader is;
String line;
String returnMsg = "Start ";
final Process p = Runtime.getRuntime().exec(PROGRAM);
System.out.println("start");
Thread waiter = new Thread() {
public void run() {
try {
p.waitFor();
} catch (InterruptedException ex) {
System.out.println("InterruptedException");
return;
}
System.out.println("Program terminated!");
done = true;
}
};
waiter.start();
is = new BufferedReader(new InputStreamReader(p.getInputStream()));
while (!done && ((line = is.readLine()) != null))
{
System.out.println(line);
returnMsg = returnMsg + line;
}
System.out.println(returnMsg);
System.out.println("End");
return;
}// main
}
I assume that there is a good reason why you want to run a java program from another java program and not just from a shell script, or by invoking an API - but if not - please reconsider.
As to your problem - if your application produces a lot of output (the one you are running as a process) - your application will hang. The p.waitFor() will halt until the process ends. But if you don't read the information from the InputStream - it will overflow and hang!
Advice #1: put the p.waitFor() at the end.
Advice #2: read this article. If I remember correctly it is the one I read when I had a similar problem. You can also google for "StreamGobbler" - it is a common name for a separate thread that "gobbles" your streams.
Advice #3: Don't forget the ErrorStream - if your application will produce too many errors - that stream will cause the process to hang as well.

Redirect Runtime.getRuntime().exec() output with System.setOut();

I have a program Test.java:
import java.io.*;
public class Test {
public static void main(String[] args) throws Exception {
System.setOut(new PrintStream(new FileOutputStream("test.txt")));
System.out.println("HelloWorld1");
Runtime.getRuntime().exec("echo HelloWorld2");
}
}
This is supposed to print HelloWorld1 and HelloWorld2 to the file text.txt. However, when I view the file, I only see HelloWorld1.
Where did HelloWorld2 go? Did it vanish into thin air?
Lets say I want to redirect HelloWorld2 to test.txt also. I can't just add a ">>test.txt" in the command because I'll get a file already open error. So how do I do this?
The standard output of Runtime.exec is not automatically sent to the standard output of the caller.
Something like this aught to do - get access to the standard output of the forked process, read it and then write it out. Note that the output from the forked process is availble to the parent using the getInputStream() method of the Process instance.
public static void main(String[] args) throws Exception {
System.setOut(new PrintStream(new FileOutputStream("test.txt")));
System.out.println("HelloWorld1");
try {
String line;
Process p = Runtime.getRuntime().exec( "echo HelloWorld2" );
BufferedReader in = new BufferedReader(
new InputStreamReader(p.getInputStream()) );
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
}
catch (Exception e) {
// ...
}
}
Since JDK 1.5 there is java.lang.ProcessBuilder which handles std and err streams as well. It's sort of the replacement for java.lang.Runtime and you should be using it.
System.out is NOT the stdout from the new process you spawned by calling exec(). If you want to see the "HelloWorld2" you must get the Process returned from the exec() call, then call getOutputStream() from that.
Simpler way to achieve objective:
ProcessBuilder builder = new ProcessBuilder("hostname");
Process process = builder.start();
Scanner in = new Scanner(process.getInputStream());
System.out.println(in.nextLine()); // or use iterator for multilined output

Categories