Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 632
mrbela Avatar asked Jan 07 '19 16:01

mrbela


People also ask

How do you know if a method throws an exception?

The calculate method should check for an exception and if there is no exception, return the calculated value to the main function i.e. v1+v2 or v1-v2; Else if an exception exists then it should print the error statement and the value that is returned from the calculate method to the main method should be 0.0(Not ...

When an exception is thrown by a method What happens next?

When a method declares that it throws an exception, it is not required to handle the exception. The caller of a method that throws exceptions is required to handle the exceptions (or throw them to its caller and so on) so that the flow of the program can be maintained.

How does PrintStream work in Java?

Working of PrintStream Unlike other output streams, the PrintStream converts the primitive data (integer, character) into the text format instead of bytes. It then writes that formatted data to the output stream. And also, the PrintStream class does not throw any input/output exception.

What does JVM do when an exception occurs?

The JVM is responsible for finding an exception handler to process the Exception object. It searches backward through the call stack until it finds a matching exception handler for that particular class of Exception object (in Java term, it is called " catch " the Exception ).


1 Answers

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);
            }
        }
    }
}
like image 58
Radiodef Avatar answered Sep 20 '22 15:09

Radiodef