I am trying to pass data from a program MainProgram
to another program TestProgram
which I invoke using Reflection. For this, i re-route Standard.in
to a ByteArrayOutputStream
containing the data I want to transmit. TestProgram
then reads from Standard.in
using a BufferedReader
and readLine()
. I execute the whole thing several times in a for-loop. The problem is this: The first time, everything works fine, from the second time on, TestProgram
reads null
from System.in
. Java Documentation states that the BufferedReader
will return null
, if the end of stream is reached. But there is definitely data in the stream and the pos
of my ByteArrayOutputStream
is also 0. Why could the BufferedReader
think that suddenly System.in
is empty or at the end of stream?
Here is the code that's manipulating the streams and invoking the method:
for(int i = 0; i < numberOfCases; i++) {
Byte[] paramBytes = getCurrentParamBytes();
InputStream inputStream = new BufferedInputStream(new ByteArrayInputStream(paramBytes));
System.setIn(inputStream);
String[] params = null;
testProgram.invoke(null, (Object) params);
}
Here is the code that's reading from System.in
:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String current = in.readLine();
I have assured myself of the state of System.in
using the debugging mode of Eclipse and everything is fine there. The fact that it only reads null
starting with the second invocation of the TestProgram
's main method is also very puzzling to me. Especially, because all values I have checked are exactly the same as they were the first time (except for the data in the stream, of course).
Sadly, I cannot change the use of the BufferedReader
because TestProgram
is not my class and has to be used as-is.
Any help would be greatly appreciated.
The problem is likely in the fact that BufferedReader
created once, on first invocation. BufferedReader
uses instance of InputStream
that you provided on first iteration of a loop. On second, third, etc invocations it still uses this stream and doesn't read from updated System.in
. I see 2 possible solutions if you can't modify source code of TestProgram
.
TestProgram
on each iteration instead of reusing old. It might help to "refresh" inner BufferedReader
if it is stored as class variable, not static.TestProgram
because it has state or BufferedReader
stored in static variable you can try following: use special kind of InputStream
that allows you to concatenate several InputStreams
on fly. Check ConcatInputStream. Example of second approach:
ConcatInputStream concat = new ConcatInputStream();
System.setIn(concat);
for(int i = 0; i < numberOfCases; i++) {
Byte[] paramBytes = getCurrentParamBytes();
InputStream inputStream = new BufferedInputStream(new ByteArrayInputStream(paramBytes));
concat.addInputStream(inputStream);
String[] params = null;
testProgram.invoke(null, (Object) params);
}
I'm not sure it will work because I don't know what is behaviour of BufferedReader if it sees end of stream on first invocation and then, on second invocation, stream suddenly not empty any more (because we've added new stream to concat
). But hopefully it will work.
There are also third approach: you can decompile TestProgram
using e.g. JD and find where instance of BufferedReader
is stored. And then you can set it to null between iterations using reflections. But it's very error prone.