How to find out the occurred exception during using a PrintStream in Java
Asked Answered
D

1

9

I have just read, that in Java the classes PrintStream and PrintWriter don't throw checked exceptions. Instead they are using a kind of an error flag which I can read invoking the method boolean checkError() (API link).

Now, I am asking myself how to find out the reason why the exception occurred. The information that there was an exception is sometimes maybe not enough, or?

Diba answered 7/1, 2019 at 16:59 Comment(0)
G
8

Based on the source code, it looks like they discard the exception. All of the catch blocks look like this:

try {
    ...
}
catch (IOException x) {
    trouble = true; // (x is ignored)
}

So the most straightforward solution is probably to not use PrintStream, if possible.

One workaround could be to extend PrintStream and wrap the output in another OutputStream which captures the exception before PrintStream catches (and discards) it. Something like this:

package mcve.util;

import java.io.*;

public class PrintStreamEx extends PrintStream {
    public PrintStreamEx(OutputStream out) {
        super(new HelperOutputStream(out));
    }

    /**
     * @return the last IOException thrown by the output,
     *         or null if there isn't one
     */
    public IOException getLastException() {
        return ((HelperOutputStream) out).lastException;
    }

    @Override
    protected void clearError() {
        super.clearError();
        ((HelperOutputStream) out).setLastException(null);
    }

    private static class HelperOutputStream extends FilterOutputStream {
        private IOException lastException;

        private HelperOutputStream(OutputStream out) {
            super(out);
        }

        private IOException setLastException(IOException e) {
            return (lastException = e);
        }

        @Override
        public void write(int b) throws IOException {
            try {
                super.write(b);
            } catch (IOException e) {
                throw setLastException(e);
            }
        }

        @Override
        public void write(byte[] b) throws IOException {
            try {
                super.write(b);
            } catch (IOException e) {
                throw setLastException(e);
            }
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            try {
                super.write(b, off, len);
            } catch (IOException e) {
                throw setLastException(e);
            }
        }

        @Override
        public void flush() throws IOException {
            try {
                super.flush();
            } catch (IOException e) {
                throw setLastException(e);
            }
        }

        @Override
        public void close() throws IOException {
            try {
                super.close();
            } catch (IOException e) {
                throw setLastException(e);
            }
        }
    }
}
Grossman answered 7/1, 2019 at 17:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.