Java System.in和自定义InputStreamReader之间的行为差异
我编写了一个JavaCLI程序,从stdin中读取行,并为每行输出一个可能的补全。我正在尝试为它提供一个gui,因此我正在尝试为Java System.in和自定义InputStreamReader之间的行为差异,java,polymorphism,inputstream,bufferedreader,Java,Polymorphism,Inputstream,Bufferedreader,我编写了一个JavaCLI程序,从stdin中读取行,并为每行输出一个可能的补全。我正在尝试为它提供一个gui,因此我正在尝试为System.in构建一个插件,以允许用户使用gui或cli 到目前为止,我得到了这个替换,当在JTextArea中输入文本时,将调用其方法add: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStre
System.in
构建一个插件,以允许用户使用gui或cli
到目前为止,我得到了这个替换,当在JTextArea中输入文本时,将调用其方法add
:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.util.LinkedList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class GuiIn extends InputStream {
protected LinkedBlockingQueue<Byte> buf;
protected boolean closed;
public GuiIn() {
closed = false;
buf = new LinkedBlockingQueue<Byte>();
}
@Override
public void close() {
closed = true;
}
/**
* add strings to read in the InputStream. Arguments are ignored if the
* stream is closed.
*
* @param s
* a string. Ignored if null
*/
public void add(String s) {
if (closed || s == null) {
return;
}
byte[] bs = s.getBytes();
LinkedList<Byte> lbs = new LinkedList<Byte>();
for (byte b : bs) {
lbs.add(b);
}
buf.addAll(lbs);
}
@Override
public int available() {
return buf.size();
}
@Override
public synchronized int read() throws InterruptedIOException {
if (closed && buf.isEmpty()) {
return -1;
}
Byte b = 0;
while (true) {
try {
if ((b = buf.poll(100, TimeUnit.MILLISECONDS)) == null) {
if (closed && buf.isEmpty())
return -1;
} else
break;
} catch (InterruptedException e) {
throw new InterruptedIOException("interrupted: "
+ e.getMessage());
}
}
return b;
}
}
导入java.io.BufferedReader;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.InputStreamReader;
导入java.io.InterruptedIOException;
导入java.util.LinkedList;
导入java.util.concurrent.LinkedBlockingQueue;
导入java.util.concurrent.TimeUnit;
公共类GUI扩展了InputStream{
受保护的LinkedBlockingQueue buf;
受保护布尔闭合;
公共语言{
关闭=错误;
buf=新的LinkedBlockingQueue();
}
@凌驾
公众假期结束(){
关闭=真;
}
/**
*添加要在InputStream中读取的字符串。如果
*溪流关闭了。
*
*@param s
*字符串。如果为null,则忽略
*/
公共无效添加(字符串s){
if(闭合| | s==null){
返回;
}
字节[]bs=s.getBytes();
LinkedList lbs=新建LinkedList();
for(字节b:bs){
lbs.add(b);
}
总重量(磅);
}
@凌驾
公共int可用(){
返回buf.size();
}
@凌驾
public synchronized int read()引发InterruptedIOException{
if(已关闭&&buf.isEmpty()){
返回-1;
}
字节b=0;
while(true){
试一试{
if((b=buf.poll(100,时间单位毫秒))==null){
if(已关闭&&buf.isEmpty())
返回-1;
}否则
打破
}捕获(中断异常e){
抛出新的InterruptedIOException(“interrupted:
+e.getMessage());
}
}
返回b;
}
}
然而,当我用newbufferedreader(newinputstreamreader(in))试用它时
并尝试readLine()
it,它似乎会阻塞,直到有足够的字符(很多),尽管我的侦听器总是在输入的文本后面加上新行
另一方面,如果中的设置为系统。在
中,每一行在输入后立即读取
因此,我的问题分为两部分:
这种差异从何而来
如何修复它
请注意,从裸GuiIn
中读取每个字节是正确的,我已经尝试过一些技巧,比如减小BufferedReader
的缓冲区大小
我还提前搜索了web:这不是关于创建模拟对象;而且也不是一个选项:它不支持追加。问题的一个根源可能是,InputStreamReader
可能会坚持阅读更远的内容,这样它就可以确定它使用的字节
->char
解码器(对它来说是不透明的)有足够的字节来生成完整的字符,而系统。in
可能对默认编码有足够的了解,以提供足够的字节
在开始使用Java进行交互式控制台操作之前,您应该熟悉类和端口
然后,我将在更高级别上进行抽象,而不是在不指定编码的情况下创建InputStreamReader
s:
interface CommandLineSource {
String readLine() throws IOException;
}
然后,您可以创建一个由FileDescriptor.STDIN
支持的,另一个由您喜欢的任何东西支持的,这样您就可以自动进行测试输入。围绕这个问题进行抽象是一个好主意,尽管在多态性方面有点失望。使用控制台似乎不合适,因为文档不能保证重定向流时控制台的存在(我打算执行批处理以分析许多完成情况)。有一件事:这与测试无关:我已经有JUnit类直接和完成类交互。无论如何,谢谢你的指点@伯纳德·保卢斯,是的。这是一件令人失望的事。我知道默认的System.out
做了很多操作系统特有的废话,试图同时充当字节和字符接收器,我怀疑System.in
类似。如果您进行了抽象,那么您可以在可用的地方使用控制台
,但当System.Console()==null
时,您可以回到缓冲读取器周围的简单包装器。事实上,是解码器导致了问题:openjdk-6的行为方式与官方sdk(java 6)相同通过查看openjdk的源代码可以证实这一点。没有完全通过确切的解码器类,但那是另一次。再次感谢!