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就是这样做的。