我正在尝试将数据从程序MainProgram
传递到我使用反射调用的另一个程序TestProgram
。为此,我将Standard.in
重新路由到包含要传输的数据的ByteArrayOutputStream
。然后,TestProgram
使用Standard.in
和BufferedReader
从readLine()
读取。我在一个for循环中多次执行整个操作。问题是这样的:第一次,一切正常,从第二次开始,TestProgram
从null
读取System.in
。 Java文档指出,如果到达流的末尾,则BufferedReader
将返回null
。但是流中肯定有数据,而我的pos
的ByteArrayOutputStream
也为0。为什么BufferedReader
会突然认为System.in
为空或流末?
这是操纵流并调用方法的代码:
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);
}
这是从
System.in
中读取的代码:BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String current = in.readLine();
我已经使用Eclipse的调试模式向自己保证了
System.in
的状态,并且一切都很好。从第二次调用null
的main方法开始仅读取TestProgram
的事实,也令我感到困惑。特别是,由于我检查的所有值都与第一次完全相同(当然,除了流中的数据)。可悲的是,我不能更改
BufferedReader
的用法,因为TestProgram
不是我的课程,必须按原样使用。任何帮助将不胜感激。
最佳答案
问题可能是因为BufferedReader
在第一次调用时创建了一次。 BufferedReader
使用您在循环的第一次迭代中提供的InputStream
的实例。在第二次,第三次等调用时,它仍然使用此流,并且不会从更新的System.in
中读取。如果您不能修改TestProgram
的源代码,我看到2种可能的解决方案。
在每次迭代中创建TestProgram
的新实例,而不是重用旧的实例。如果将内部BufferedReader
存储为类变量而不是静态变量,则可能有助于“刷新”内部TestProgram
。
如果您无法创建BufferedReader
的新实例,因为它已将状态或InputStream
存储在静态变量中,则可以尝试以下操作:使用特殊类型的InputStreams
允许您动态连接多个concat
。检查ConcatInputStream。
第二种方法的示例:
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);
}
我不确定它是否会工作,因为我不知道BufferedReader的行为是什么,如果它在第一次调用时看到流的结尾,然后在第二次调用时突然发现流不再为空(因为我们已经向其中添加了新的流
TestProgram
)。但是希望它会起作用。还有第三种方法:您可以使用例如反编译
BufferedReader
JD并找到实例的存储位置。然后您可以使用反射将其设置为零。但这很容易出错。关于java - BufferedReader返回null,即使它正在读取的流位于pos 0,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20332011/