Danny Lo Danny Lo -4 years ago 135
Java Question

Try-with-resources and System.in

Ok, here is a probably not the best question, but I'm stuck with it and can't find answer to this on the net.

This code won't read from standard input the second time:

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());
}


I know java's try-with-resources recursively closes all streams in the chain, so after the first reading
System.in
is closed. Is there any good workaround for that? Or should I really handle stream closing myself?

upd:
I tried to handle the stream closing myself (that is java6-style). Here's a code if somebody's interested. But I noticed that this chain-closing behaviour comes not from try-with-resources bur rather from the implementation of close-methods. So I didn't win anything from that attempt.

I pick fge's solution because it's the most verbose one. It worked for me directly.

All in all it seems quite strange to me, that java doesn't have such solution out of the box since there are system streams which shouldn't be closed.

Answer Source

One workaround would be to create a custom InputStream class which would delegate to another one, except that it wouldn't .close() it when itself is closed. As in:

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();
    }
}

Note that a probably easier solution in your case would be to extend InputStreamReader as the class is not final and just override .close().

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download