好的,这可能不是最好的问题,但是我坚持下去并且无法在网上找到答案。
此代码第二次不会从标准输入读取:
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in)))
{
input = br.readLine();
}
catch (final Exception e)
{
System.err.println("Read from STDIN failed: " + e.getMessage());
}
// do some processing
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in)))
{
input = br.readLine();
}
catch (final Exception e)
{
System.err.println("Read from STDIN failed: " + e.getMessage());
}
我知道java的try-with-resources以递归方式关闭链中的所有流,因此在第一次阅读System.in
之后关闭。那有什么好的解决方法吗?或者我应该自己处理流关闭吗?
UPD: 我试图处理关闭自己的流(这是java6风格)。如果有人感兴趣的话,这里是code。但是我注意到这种关闭链的行为不是来自try-with-resources bur而是来自close方法的实现。所以我没有从那次尝试中获得任何好处。
我选择了fge的解决方案,因为它是最冗长的解决方案。它直接对我有用。
总而言之,我觉得很奇怪,java没有开箱即用的解决方案,因为系统流不应该被关闭。
答案 0 :(得分:1)
一种解决方法是创建一个自定义InputStream
类,该类将委托给另一个,除了它本身关闭时不会.close()
。如:
public class ForwardingInputStream
extends InputStream
{
private final InputStream in;
private final boolean closeWrapped;
public ForwardingInputStream(final InputStream in, final boolean closeWrapped)
{
this.in = in;
this.closeWrapped = closeWrapped;
}
public ForwardingInputStream(final InputStream in)
{
this(in, false);
}
@Override
public int read()
throws IOException
{
return in.read();
}
@Override
public int read(final byte[] b)
throws IOException
{
return in.read(b);
}
@Override
public int read(final byte[] b, final int off, final int len)
throws IOException
{
return in.read(b, off, len);
}
@Override
public long skip(final long n)
throws IOException
{
return in.skip(n);
}
@Override
public int available()
throws IOException
{
return in.available();
}
@Override
public void close()
throws IOException
{
if (closeWrapped)
in.close();
}
@Override
public synchronized void mark(final int readlimit)
{
in.mark(readlimit);
}
@Override
public synchronized void reset()
throws IOException
{
in.reset();
}
@Override
public boolean markSupported()
{
return in.markSupported();
}
}
请注意,在您的情况下,一个可能更简单的解决方案是扩展InputStreamReader
,因为该类不是final
而只是覆盖.close()
。
答案 1 :(得分:1)
我认为这个问题比try-with-resources更普遍,因为其他人可能会使用旧版本的Java并自己关闭BufferedReader
。这会让你处于和现在一样的情况
我找到了relevant SO question这个更一般的情况。给出的答案是使用Apache Commons IO,它有一个名为CloseShieldInputStream
的流代理。如果这是您将使用的Commons IO中唯一的东西,您也可以考虑自己编写代理类,而不是依赖于像Commons IO这样的大型库。
答案 2 :(得分:1)
这确实是一个小问题。我不知道,如果公共库(Apache Commons IO,Google Guava,...)中存在某些解决方案,但您可以自己编写一个处理此问题的简单类。
编写一个InputStream
的类并包装InputStream
,通过将调用委托给包装的流来覆盖所有公共方法,但close
方法除外,什么都不做。
public final class NonClosingInputStream extends InputStream {
private final InputStream wrappedStream;
public NonClosingInputStream(final InputStream wrappedStream) {
this.wrappedStream = Objects.requireNonNull(wrappedStream);
}
@Override
public void close() {
// do nothing
}
// all other methods
}
在此类的实例中包装System.in
将解决您的问题。
答案 3 :(得分:0)
这是一个老问题,但这是一个更简洁的解决方案:
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in)
{public void close() throws IOException {}})) {
input = br.readLine();
}
这样可以通过将System.in
空格式InputStreamReader
方法传递给close()
的构造函数来确保不会关闭BufferedReader
。