Java 尝试使用资源和System.in
好的,这里有一个可能不是最好的问题,但我被它困住了,在网上找不到答案 此代码不会第二次从标准输入读取:Java 尝试使用资源和System.in,java,stream,stdin,try-with-resources,Java,Stream,Stdin,Try With Resources,好的,这里有一个可能不是最好的问题,但我被它困住了,在网上找不到答案 此代码不会第二次从标准输入读取: try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) { input = br.readLine(); } catch (final Exception e) { System.err.println("Read from STDIN failed: " + e.getMes
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风格)。如果有人感兴趣,这里有一个例子。但是我注意到,这种链式关闭行为不是来自try with resources,而是来自close方法的实现。所以我没有从那次尝试中赢得任何东西
我选择fge的解决方案是因为它是最冗长的。它直接对我起作用
总而言之,我觉得很奇怪,java没有现成的解决方案,因为存在不应该关闭的系统流。一种解决方法是创建一个自定义的
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()
我认为这个问题比使用参考资料更普遍,因为其他人可能使用较旧版本的Java并关闭BufferedReader
。这将使您处于与现在相同的情况。我找到了一个更一般的例子。这里给出的答案是使用ApacheCommonsIO,它有一个名为的流代理。如果这是您将使用的公钥IO中唯一的东西,那么您也可以考虑自己编写代理类,而不是依赖于一个大型库,比如Cason IO。p> 这确实是一个小问题。我不知道公共库中是否存在一些解决方案(ApacheCommonsIO、GoogleGuava等等),但是您可以自己编写一个简单的类来处理这个问题 编写一个类,该类是一个
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
}
将
系统包装在该类的一个实例中将解决您的问题。这是一个老问题,但这里有一个更简洁的解决方案:
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in)
{public void close() throws IOException {}})) {
input = br.readLine();
}
这确保了系统。
中不会通过将带有空重写close()
方法的InputStreamReader
传递给BufferedReader
的构造函数来关闭。他正在寻求解决方法。您可以创建自己的InputStream
类,该类不会关闭.close()
上的基础资源;尽管这违反了.close()
承包商,但在这种情况下,您可以避免使用try-with-resources,因为您不希望关闭流,而try-with-resources就是这样做的。