I have a small program whereby in the main thread, I ask for input from the user in the console.
System.out.print("Alternatively, enter peer's ID to connect:");
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader bReader = new BufferedReader(reader);
String peerID = bReader.readLine();
and in a separate thread I listen from my sockets' InputStream. If I receive something from this stream, i then try to "unblock" the readLine by calling System.in.close() without waiting for the user's input. The main thread can then proceed to do something with the information obtained either from the socket's read or from the user.
Somehow it seem to work on my Mac, but if I try it on Windows, stepping through the debugger, I've found that System.in.close() blocks and the whole program will hangs.
Any idea why and how should i unblock readline()? Otherwise what would be a good way of rewriting the logic?
You could try to close bReader instead, but a sounder approach would be to use interruptible io in the nio package and possibly the Console. I would try using the Console.read(CharBuffer), and interrupt the thread. That "should" work. Haven't tested though...
Update: But a Selector would maybe suit your purpose even better. Listen to both your socket and System.in, and act on the one that provides input?
Related
I have named pipe .\pipe\pipe1 on Windows I want to read from with Java.
From the documentation, FileChannel should be interruptible. Read should throw a ClosedByInterruptException if the reading thread is interrupted from another therad. This probably works for regular files, but I now have a named pipe.
My situation is like this:
RandomAccessFile raf = new RandomAccessFile("\\\\.\\pipe\\pipe1", "r");
FileChannel fileChannel = raf.getChannel();
// later in another thread "readThread"
fileChannel.read(buffer);
// outside the thread reading
readThread.interrupt();
The problem is that the call to interrupt will block and read will remain blocked until something to the named pipe is written so that read will stop blocking.
I need to be able to abort/cancel the read when nothing is written to the pipe while it is not closed yet.
Why does interrupting with the NIO classes not work? Is there a solution to this problem that does not involve busy-waiting or sleep with ready? What would be the best solution for this problem or is there a workaround?
I have not figured out a real solution to the question how to cancel the read. But I needed to adjust anyway and will now explain why. If you have anything to add to the original problem of the blocked read, you can post an additional answer.
A named piped could be treated like a file and opened separately for reading and writing with classic Java IO streams. However, a named piped is often used like a socket and as such, it requires a single file open. So I one could use Java IO streams like this:
RandomAccessFile raf = new RandomAccessFile("\\\\.\\pipe\\pipe1", "rws");
FileChannel fileChannel = raf.getChannel();
InputStream fis = Channels.newInputStream(fileChannel);
OutputStream fos = Channels.newOutputStream(fileChannel);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
PrintWriter pw = new PrintWriter(fos, true);
Now a problem one will later notice is this: If you write while reading, things will get locket up. It seems concurrent reading/writing is not possible, which is outline here.
To solve this, I used a ReentrantLock set to fair to switch from reading/writing. The reading thread is checking readyness and can be triggered with interrupt if one finishes writing and expects a response after this. If ready, the reading buffer is drained. If it is not ready, an interval can be scheduled or simulated for sporadically expected messages. This last part is not optimal, but actually works very well for my use case.
With this, one can build a solution where all threads can be orchestrated to terminate correctly with no blocking and minimal overhead.
I am using ProcessBuilder to input and receive information from a C++ program, using Java. After starting the process once, I would like to be able to input new strings, and receive their output, without having to restart the entire process. This is the approach I have taken thus far:
public void getData(String sentence) throws InterruptedException, IOException{
InputStream stdout = process.getInputStream();
InputStreamReader isr = new InputStreamReader(stdout);
OutputStream stdin = process.getOutputStream();
OutputStreamWriter osr = new OutputStreamWriter(stdin);
BufferedWriter writer = new BufferedWriter(osr);
BufferedReader reader = new BufferedReader(isr);
writer.write(sentence);
writer.close();
String ch = reader.readLine();
preprocessed="";
while (ch!=null){
preprocessed = preprocessed+"~"+ch;
ch = reader.readLine();
}
reader.close();
}
Each time I want to send an input to the running process, I call this method. However, there is an issue: the first time I send an input, it is fine, and the output is received perfectly. However, the second time I call it, I receive the error
java.io.IOException: Stream closed
which is unexpected, as everything is theoretically recreated when the method is called again. Moreover, removing the line the closes the BufferedWriter results in the code halting at the following line, as if the BufferedReader is waiting for the BufferedWriter to be closed.
One final thing - even when I create a NEW BufferedWriter and instruct the method to use that when called for the second time, I get the same exception, which I do not understand at all.
Is there any way this can be resolved?
Thanks a lot!
Your unexpected IOException happens because when Readers and Writers are closed, they close their underlying streams in turn.
When you call your method the first time, everything appears to work. But you close the writer, which closes the process output stream, which closes stdin from the perspective of the process. Not sure what your C++ binary looks like, but probably it just exits happily when it's done with all its input.
So subsequent calls to your method don't work.
There's a separate but similar issue on the Reader side. You call readLine() until it returns null, meaning the Reader has felt the end of the stream. But this only happens when the process is completely done with its stdout.
You need some way of identifying when you're done processing a unit of work (whatever you mean by "sentence") without waiting for the whole entire stream to end. The stream has no concept of the logical pause between outputs. It's just a continuous stream. Reader and Writer are just a thin veneer to buffer between bytes and characters but basically work the same as streams.
Maybe the outputs could have delimiters. Or you could send the length of each chunk of output before actually sending the output and distinguish outputs that way. Or maybe you know in advance how long each response will be?
You only get one shot through streams. So they will have to outlive this method. You can't be opening and closing streams if you want to avoid restarting your process every time. (There are other ways for processes to communicate, e.g. sockets, but that's probably out of scope.)
On an orthogonal note, appending to a StringBuilder is generally more efficient than a big loop of string concatenations when you're accumulating your output.
You might also have some thread check process.exitValue() or otherwise make sure the process is working as intended.
Don't keep trying to create and close your Streams, because once you close it, it's closed for good. Create them once, then in your getData(...) method use the existing Streams. Only close your Streams or their wrapping classes when you're fully done with them.
Note that you should open and close the Streams in the same method, and thus may need additional methods or classes to help you process the Streams. Consider creating a Runnable class for this and then reading from the Streams in another Thread. Also don't ignore the error stream, as that may be sending key information that you will need to fully understand what's going on here.
I have a very simple question.
Based on Java I/O scheme, whenever a thread is waiting for some data, so it will be blocked? is it true? something like this.
byte[] _buff=new byte[1024];
int _r=_in.read(_buff);//it blocks until some data is available
and the just possible way to give up reading is closing the stream by another thread, is it right? something like this.
void run(){
_in.close();
}
so if I am right with above scenarios, so why this is impossible just interrupt a thread which is reading from System.in by closing the stream. I run a thread that just waits for 5 seconds then wants to interrupt/give up rest of the reading from the stream.
void _read_data(){
System.out.print("enter y to save the workspace ");
new Thread(_cancel_thread).start();
int _r=System.in.read();//blocks
}
///////////
void run(){
try{
Thread.sleep(5000);
System.in.close();//doesn't work.
}catch(Exception _ex){}
}
Questions:
1.How to close the stream?! why the closing stream thread cannot close the stream?!
2.Once the stream got closed, how to open it again?!
For the first question, I think this is because maybe(I don't know, not sure) the stream is kinda locked by lower-level, so while it's locked, another thread is just waiting to acquire the lock and close it.
and for second one, I really don't know is there any class(stream) which works with keyboard stream or not, but why do you really want to close it? just keep the stream somewhere (like in=System.in), then redirect the standard stream to another stream by calling System.setIn(newStream), then whenever you want to give keyboard stream back, reset the stream with the reference.
Closing the default system input stream is not good idea, I suggest you utilize either JConsol or jNativeHook, these guys do not block, instead they listen for events.
I'm using a UNIX socket to facilitate communication on and Android device between a system level daemon I've got running in C and an application I've got running in Java. I'm much more of a C coder than a Java coder, so I'm having some issues when trying to read in data from the socket on the Java side. Currently, my code is as follows:
try{//Prepare to write the command and read the ACK
InputStream is = receiver.getInputStream();
OutputStream os = receiver.getOutputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
os.write(message.getBytes());
//FIX THIS!! The following assumes that there is a newline-
// terminated chunk of data waiting for us in the buffer. If
// that assumption is wrong, the code will hang. Find some way
// to determine if/how much data is waiting for us in the socket!
String str = in.readLine();
is.close();
os.close();
receiver.close();
return str;
}catch(IOException ex){
Log.e(TAG,(ex.toString()+"\n"));
return null;
}
As my comment indicates, this implementation works(ish), but has the very bad design flaw of requiring that the server side socket code responds with a newline terminated string. If that's not the case, the world ends.
What I'm trying to figure out is if there is a better means of accomplishing this task. Is it possible to determine if there is any data waiting to be read in a buffered reader, and if so, what the size of that data is? If not, is there a better way of reading in data over a UNIX socket on the Java side of Android that I'm not familiar with?
Thanks in advance!
if the protocol requires a newline, your impl is appropriate. the code SHOULD be blocked until a newline is read. what else can you do but wait?
of course, usually you don't want to wait forever, you need a timeout. see Socket.setSoTimeout()
if a newline is not necessarily given by server, and you just want to read any data as soon as available, use InputStream.read()
i want to read from input stream when i connect to a server socket.
but there may exist some delays between messages how can i read from input stream without busy loop ?
string mes = socketReader.readLine();
above line returns null when no input provided in socket input stream.
i want to be notified somehow when a message is ready in input stream.
tnx
Have you looked asynchronous IO?
In a GUI context, SwingWorker may help: let doInBackground() do the reading, use process() for interim reuslts, and done() to wrap up. You can register a PropertyChangeListener to drive a progress indicator. This article expands on the idea, and a back port to Java 1.5 is available. Here's a simple example that reads from a JDBC source instead of a stream, but the idea is the same.