Running a continuous batch process in Java - java

I have a batch file which performs the operation of listening to the microphone and converting it to text (i am using pocket sphinx).
The command I am using to run the batch file is pocketsphinx_continuous.exe -dict <dict name> -lm <language model> -hmm <acoustic model location>. The batch file starts off and keeps listening to the microphone. Whenever we finish speaking a sentence it converts it into text on the command prompt. Since this continuously running we terminate this task by Ctrl-C.
I was trying to make this into a standalone Java application. I wanted to run this batch file through Java, so i used Runtime.getRuntime().exec("cmd /c start pocketsphinx_continuous.exe ...") with all the parameters. However strangely, it starts the batch process in a separate command prompt but immediately exits. I tried to use process.waitfor(), however it simply starts executing the batch process and then terminates. I havent called process.destroy, so i am unable to figure out why it exits the batch process.
The other question is since the batch file is running continuously, after every spoken sentence has been transcribed , I wish to get the output in my Java application. I know i can redirect the batch process to a file and then read the file, was just wondering if there is a more direct process. Could you please help me figure out where I am making a mistake.

You should use Process.getInputStream() and Process.getErrorStream() to find out what messages it prints out.
If it is exiting instantly, you might need to get the exit code (Process.waitFor()) and check the error logs from the error stream.
Also, if you can post some of your code we might be able to help. In general, these problems are due to incorrectly configured paths or command strings.
A possible fix would be to use the ProcessBuilder from Java 1.5 thusly:
// Note the lack of "cmd \c" - you shouldn't need to run it in a cmd window!
ProcessBuilder pb = new ProcessBuilder("pocketsphinx_continuous.exe",
"dict", "1121.dic",
"-lm", "1121.lm",
"-hmm", "hub4/hmm");
Process p = pb.start();
// TODO for you:
// 1. Create Threads to handle the input
// 2. Store the Process instance so that you can call p.destroy() later.
// 3. If interested, have a Thread doing p.waitFor() to get the exit code.
As Joachim Sauer mentioned in the comments, this Javaworld article explains a lot of the gotchas associated with the Process API, so have a read through. I haven't had a chance to play with the improvements made in JDK7 to the Process API, and by the looks of things Oracle are improving it again for JDK8 (JEP 102).

You can also use Timer and TimerTask to schedule your batch scan process in background. You can use this to specify infinite running task.

Related

How do i launch a GUI Terminal and run commands on it in java

I have a program which runs when you double click it. What i want to do is:
Double click a jar File
Launch some GUI
And Run Commands in the terminal through the java program
(just an example, this is not what i want to do)
I Tried this:
public class Main{
public static void main(String [] args){
Runtime.getRuntime().exec("/bin/bash sudo SOME_COMMAND_HERE");
}
}
(SOME_COMMAND_HERE is just a replacement)
It didn't launch a terminal.
(i have the GUI part so no need to write code for that)
So how do i do this? I have been spending a past day or two for just finding answers on stack overflow, and intense googling.
Plus the Reason why i need it is because i want to show the user some progress and entering the password when running sudo commands.
Can some Please help? Thanks in advance.
In your example the process might get stuck as you are not reading it's stdout and stderr streams. From the Process documentation:
Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the process may cause the process to block, or even deadlock.
So essentially you are just asking how to execute a process from Java. It is irrelevant that to the user your program would display a terminal-like UI. Knowing this we could rephrase your question and find answers like
Starting a process in Java?
Java Execute a bash script using Java process builder
Execute process from Java irrespective of underlying OS
Java ProcessBuilder - get Output immediately
https://alvinalexander.com/java/java-exec-processbuilder-process-1/

Can Clojure Capture Standard Out of Existing Process?

In a Clojure program, how do you read from standard out? I want to do that, or pipe the standard output, to an input stream that I create. The standard output in Clojure is a java.io.PrintWriter .
I have a Samza job, started by a Clojure program. There's also an nrepl server to which I can remotely connect. After connecting, I need to be able to tap into and tail standard out (to which jobs write their output).
1) As per this SO question, with-out-str (see here) lets us temporarily bind *out* (to a java.io.StringWriter), so that your executed code writes to a string. But that doesn't let me tap into the existing *out*.
2) If you look at clojure.java.shell (see here), it gets the JVM's Runtime and exec's a Process on it. From that process, you can get its standard output stream. But again, that's not the default standard out (*out*) I'm looking for.
3) This SO question gets close to what I'm trying to do. But again, I'm connecting to an existing process, and want to tail out its standard output.
Is this possible in Clojure (see here)? Has anyone solved this?
Process output is not a publish subscribe model, so in effect when a process puts a character into it's output buffer, exactly one process gets to pull it off that buffer. If you have a program that was started by a shell that shell process if reading it's output and writing it to a terminal (or reading and ignoring it). If you attach your process after the process that started it and start trying to grab the data, you will most likely not get anything because the parent process will get it first. I just tried this from two terminals:
Terminal 1:
cat
Terminal 2:
ps -ef | grep cat
tail -f /proc/24547/fd/2
Terminal 1:
hello
Terminal 2:
< nothing >
The string "hello" printed to terminal 1, the process that started it.
It's tempting then to say "well what if nobody reads the output, then it will be there for me to get". While this sounds good it runs into the problem that these are fixed sized buffers, so as soon as the output buffer is full the process that is trying to write to it blocks (is prevented from running at all) until someone reads the output to unblock it.
The general solution is to pipe the process you want to tail later to the tee command which writes the output to a file and passes it to whatever was reading it.
command-to-watch arg1 arg2 | tee logfile.potentially-huge
Though if you go this route you should rotate the log file before your disk fills. Make sure you empty the log file with exactly this command
echo > logfile.potentially-huge
or use your program to make a truncate call to the file. simply deleting the file will remove it's name from the log directory without deleting it, it will silently continue to grow taking up disk space and the new file will get no output ever.
This is basically why we built log libraries like log4j (in the 90s) and syslog (in the 80s).
If you still want to get hackish crazy on this, turn to tmux, it can do anything, and changes the way people work with text. In all seriousness you should change the way the other process creates it's output to make it easier to get.

How to disable console popup and know when a process created by ProcessBuilder has finished so that it can be destroyed

I am creating java process using ProcessBuilder for ghostscript to convert pdf into tiff as below
process = new ProcessBuilder("D:\\ghost-script\\gs\\gs9.02\\bin\\gswin64.exe","-q", "-dNOPAUSE", "-dBATCH", "-dMaxStripSize=8192", "-sDEVICE=tiffg4", "-r300x300", "-dDITHERPPI=200", "-sOutputFile=D:\\ghost-script\\example\\output.tif", "D:\\ghost-script\\example\\input2.pdf", "-c", "quit").start();
Now I have two problems.
This process open console popup which I don't need as it has to run on server. What parameter I can set to disable that console popup.
Input file can of any be of any size. How can I know when the process has completed so that I can destroy it. I don't want Thread.sleep(time-to_sleep). Because for different size of input file it is different and if I take upper limit, it will hamper performance for lower size files badly.
So what can I do to destroy the process as soon as it get completed?
Any help is much appreciated.
For your first question, the window comes from the executable you launch, you may want to use
gswin64c.exe
See this topic : Ghostscript suppress output windows when called by command line
For your second question, use waitFor() on the Process object.
process.waitFor();

daemonize java program - go background after input some data

I tried to find a solution for the following use case (on Linux):
Start the program, show some information to the stdout, input some information such as username/password.
The program validate the username/password, then goes to background and run as a daemon.
I did not find a way to do this in Java. There are several sulotions to daemonize java program (such as jsvc, or this: http://barelyenough.org/blog/2005/03/java-daemon/ ). But seems they all do not work for this situation, because the program just goes to background from the beginning, there is no chance to input information before it goes to background.
I don't believe that there's a way to do this purely in java. You could make it work by writing an init script which accepted the command line parameters before spawning the java process in the background. You could use -D command line arguments to pass the user input to the java process.

Using java Process builder to play wav file

I would like to send the following command below from a java program, but not overly bothered about reading the response. any idea how I can do this
the command below plays the wav file from the command prompt
aplay ~/javafx/examples/PrayerTime/src/Audio/athan1.wav
I am trying the code below but it is not playing anything! from my java program
ProcessBuilder processBuilder = new ProcessBuilder("bash", "-c", "aplay ~/javafx/examples/PrayerTime/src/Audio/athan1.wav");
try {
Process process = processBuilder.start();
} catch (IOException ex) {
Logger.getLogger(JavaFXApplication4.class.getName()).log(Level.SEVERE, null, ex);
}
Andrew is absolutely right when he writes ignoring the output is the core of the problem.
When you start a process via processBuilder.start(), you are basically launching another process that has a life of its own. It's fire and forget. The only feedback you get via thrown exceptions is when the actual lauching didn't succeed. It says nothing about whether the launched process succeeded in what it was supposed to do.
Since you don't see an error message, the launching of the process went fine.
Now, using aplay and ~ suggests, that you are on some kind of Unix, probably Linux. There a process prints regular output to the standard out stream and error output to standard error stream. It also returns an exit code, that indicates whether things went smoothly or not. Both the exit code (you can get it from the process object by using waitFor()) and the error stream (also available from the process object) give you all the necessary info whether a process succeeded and if not, why not.
That all said, you might really want to use Runtime.exec() as it is much less complicated—at least until you know how to call your process without error.

Categories

Resources