Get acknowledgment of print from a printer - java

I am using the following code to give print to a network Lipi Printer (cc2 is printer name)
Process p = Runtime.getRuntime ().exec ("lp -dcc2 abcd.txt");
BufferedReader reader = new BufferedReader (
new InputStreamReader (p.getInputStream ()));
String line;
while ((line = reader.readLine ()) != null) {
System.out.println (line);
}
The problem starts when I run this in loop(> 4000) and a few of the prints get lost in the network and don't get printed.
I want to catch those lost prints and reprint them.
How can I get the printer to acknowledge the print has been received.

Check manual for your implementation of lp command. Some implementations can notify when printing is done, but the form of such notification may vary. Also there is -m switch that tells lp to send an e-mail to a user who initiated printing, once printing is done. Maybe you can somehow check these e-mails from your Java application. Anyway, this question is more about printing system of your OS rather than about Java.

Related

Separating Get request Response body in java Socket programming

I'm trying to write a curl like program using java, which uses only java socket programming (and not apache http client or any other APIs)
I want to have the option of showing whole or only the body of the response to my get request to user. Currently came up with the following code:
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String t;
while ((t = br.readLine()) != null) {
if (t.isEmpty() && !parameters.isVerbose()) {
StringBuilder responseData = new StringBuilder();
while ((t = br.readLine()) != null) {
responseData.append(t).append("\r\n");
}
System.out.println(responseData.toString());
parameters.verbose = false;
break;
} else if(parameters.isVerbose())// handle output
System.out.println(t);
}
br.close();
When the verbose option is on, it works quick and shows the whole response body in less than a second. but when I want to just have the body of the message it takes too much time(approx 10 sec) to hand it out.
Does any one knows how can it be processed in a faster way?
Thank you.
I'm going to assume what you mean by slow is that it starts displaying something almost immediately but keeps on printing lines for a long time. Writing to the console takes time, and you're printing each line invidually while in the other code path you first store the entire response in memory and then flush it to the console.
If the verbose response is small enough to fit in memory, you should do the same, otherwise you can decide on an arbitrary number of lines to print in batches (i.e; you accumulate n lines in memory and then flush to the console, clear the StringBuilderand repeat).
The most elegant way to implement my suggestion is to use a PrintStream wrapping a BufferedOutputStream, itself wrapping System.out. All my comments and advices are condensed in the following snippet:
private static final int BUFFER_SIZE = 4096;
public static void printResponse(Socket socket, Parameters parameters) throws IOException {
try (BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream printStream = new PrintStream(new BufferedOutputStream(System.out, BUFFER_SIZE))) {
// there is no functional difference in your code between the verbose and non-verbose code paths
// (they have the same output). That's a bug, but I'm not fixing it in my snippet as I don't know
// what you intended to do.
br.lines().forEach(line -> printStream.append(line).append("\r\n"));
}
}
If it uses any language construct you don't know about, feel free to ask further questions.

java println blocked after communicating with exe if i do not close the stream

I am currently interfacing a GUI to an UCI chess engine. For this purpose i am creating the engine process using:
try {
process = Runtime.getRuntime().exec(enginePath);
} catch (IOException e) {
System.err.println("ENGINE NOT FOUND");
e.printStackTrace();
}
and i am sure that i am able to open the engine.
When engine is opened, there is no significant stream outputted from engine. In order to initiate communication, I have to send specific commands to the engine. The engine will respond then... Therefore it is working in a command/response approach(not immediately streaming data when opened or talking without spoken to). In order to communicate i have a send message block. In this block write a message to the engine using its outputstream and get input using its standart input stream as in the following send method:
private String sendCommand(String command) {
stdin = new PrintWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errReader = new BufferedReader(newInputStreamReader(process.getErrorStream()));
String answer = "";
stdin.println(command);
stdin.flush();
stdin.close();
try {
String line = "";
while ((line = inputReader.readLine()) != null) {
System.out.println(line);
answer = line;
}
inputReader.close();
} catch (IOException ioe) {
System.err.println("READ ERROR");
ioe.printStackTrace();
}
try {
String line = "";
while ((line = errReader.readLine()) != null) {
System.err.println(line);
}
errReader.close();
} catch (IOException ioe) {
System.err.println("READ ERROR");
ioe.printStackTrace();
}
return answer;
}
By the way the whole engine is working in a single seperate thread other than the main GUI thread. Therefore no overloading for the GUI. However i didnot seperate the stdin stderr and output methods in individual threads since i suppose there will be only stdin and the one that i will write to the engine. For the time being i assume they will not collide.
With these codes i am able to communicate with the engine and i can see the outputs in the console. However due to stdin.close(); i can only use this method once (In the seconds time i have a STREAM CLOSED error). The chess engine is needed to be communicated in command/response approach many times when opened, without restarting the exe in each time. The problem is that if i remove the line : stdin.close(); yes the communication continues, but my console is blocked by this communication. I.e. i cannot println to the console for debugging purposes anymore. Which is very critical because my main debugging weapon is system.out.println. If i do not remove stdin.close(); i have to restart executable each time i want to send message and i do not want that. **The strange part is that i can see the messages coming from the engine in my console due to "System.out.println(line);" line in the send method; however i cannot print anything on the console once the code exits the method. **
EDIT: Actually after this block:
while ((line = inputReader.readLine()) != null) {
System.out.println(line);
answer = line;
}
System.out.println starts not to work.
EDIT: The problem seems not to be with println but any statement after while loop.
Why statements after while loop is not getting executed?
according to this, it seems that since the stream is never closed, "while loop" is stuck(?). Actually when printing inside while loop, at some point(after a stream is finished), the prints stop, which must indicate while loop is finished. Therefore if it is finished, it should continue on the next statements, shouldn't it? Anyway, the messages from the engine had a set of strings at end of each stream; therefore when i encounter one of them i am breaking the while loop.
Note: it is also interesting that : accumulating data as: "receivedString += line"; doesnot work,i.e. data is not accumulated. In order to fix it i luckily made it "receivedString = receivedString + line + "\n""; and it worked.. I dont know why.
You're reading the input until end of stream, so it won't stop reading until end of stream occurs. End of stream means that the peer has closed the connection in this case. That won't happen for a process's output or error stream until the process exits. You'll have to find some other loop termination condition, or else consume the stdout and stderr in separate threads.

BufferedReader blocking when reading from process.getErrorStream()

When I run this code and the call graph is really large, the program prints to the last line that opt outputs and is blocked at readLine, even though there is nothing left. Anyone know what the problem is? opt -print-callgraph file sends the call graph to the error stream. I tried executing opt -print-callgraph file 2> callgraph so that I can read from a file instead but it complains that there are too many positional arguments.
Oddly enough, the code runs fine for call graphs that are small in size.
I tried using ProcessBuilder as well but I get the same problem.
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("opt -print-callgraph " + file);
BufferedReader in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String s = null;
try {
// Gets stuck at readLine after printing out the last line.
while ((s = in.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
in.close();
}
You need to read both streams, in separate threads, or else merge them so you're reading them both at the same time. Otherwise the process can block if output is unconsumed. In this case there must be unconsumed output in stdout which is blocking the process, which means it won't finish, which means it won't close stderr, which means reading stderr will block.

In Java, how do I read the content line by line of another console application that's running?

I have a .exe program called Blockland.exe running. It uses a game engine called TorqueScript but it is a console application that I think uses c++ to make it an application. People have made programs which stream the console of blockland.exe before but are nowhere to be found.
In general, how would you get the output of another running console application? Once I get the lines I know how to do what I need to do with it, but how would I get the output of the console application using Java?
ProcessBuilder in java provides a way to execute an external OS command and pipe input and read output from the external command. Here is a sample which does that:
List<String> command = new ArrayList<String>();
command.add("/path/to/Blockland.exe");
command.add("Other arguments");
ProcessBuilder procBuilder = new ProcessBuilder(command);
Process proc = procBuilder.start();
ProcessOutputReader outputReader =
new ProcessOutputReader(proc.getInputStream());
ProcessOutputReader errorReader =
new ProcessOutputReader(proc.getErrorStream());
Thread out = new Thread(outputReader);
out.start();
Thread error = new Thread(errorReader);
error.start();
proc.waitFor();
Where ProcessOutputReader is a class that implements Runnable. It starts reading from the stream provided in constructor until the end-of-file occurs in the stream. This is the thread that can read the output and process it. Note that you must process the streams using separate threads, since the buffer given by java/OS for the child processes are limited. If the child processes start putting too much data in either stream (error/output) and the buffer becomes full, it'll hang.
For example it may look like (implementation is not complete):
public class ProcessOutputReader
{
public void run()
{
int ch;
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(inpStream));
// The output can be of any size. So read in chunks
String line = reader.readLine();
while(line != null)
{
// handle line
line = reader.readLine();
}
}
catch (Exception e)
{
// handle exceptions
}
}
}

Sending input to stdin and getting the full output in Java - Festival TTS

I'm trying to use the Java Runtime.getRuntime().exec(String) command to run Festival, then use OutputStreamWriter to write some commands to the outpustream of the process.
This works great, and I'm able to do something like this:
Process p = Runtime.getRuntime().exec("festival");
Writer w = new OutputStreamWriter(p.getOutputStream());
w.append("(SayText \"Hello World\")");
w.flush();
Obviously the way I can tell this works is that it speaks the text through the speakers.
What I am having a real hard time doing is getting the text output from what I would see in the terminal. I'm trying to run some other commands (such as (voice.list)) which output text, presumably to stdout.
For example, I've tried using a BufferedReader in the following way:
BufferedReader reader = new BufferedReader (new InputStreamReader(p.getInputStream()));
w.append("(voice.list)");
w.flush();
String output = "";
String line = reader.readLine();
System.out.println(line);
while ((line = reader.readLine()) != null)
{
System.out.println("Reading: " + line);
output += line;
}
(The System.out.println's is just for debugging, I would do the entire thing in a cleaner way if I was able to get it to work.)
No matter what code I try, I'm never able to get any output from Festival. I can get output from other commands. E.G. I have tried this code as well http://en.allexperts.com/q/Java-1046/2008/2/Runtime-getRuntime-exec-cmd.htm and it works with many other commands (like ls) but not Festival.
Does anything have any idea how I would be able to get this to work?
Thanks.
Festival may output it's text on stderr instead of stdout. Try replacing
p.getInputStream()
with
p.getErrorStream()

Categories