On Jun 4, 5:30 am, Reinier Zwitserloot <[email protected]> wrote:
> The problem with that, is two fold:
>
> 1) It's easy to forget to write 'flush()'. I suggest a code checker or
> an annotation processor that warns you if you forget, and
>
> 2) Theoretically, flush() does slightly less than close(). For
> example, close() will also have to update certain file descriptors,
> depending on file system. It's quite rare, so not that big of a deal,
> but nevertheless, in rare cases, your program will silently not make a
> file. Good thing it's rare, because silently failing to save data is a
> massive disaster.

An example is ZipOutputStream.  close() can throw an IOException
even if flush() was called immediately before-hand.  It would be
useful to know for which classes that implement Closeable and
Flushable
you can count on close() succeeding immediately after flush().

> FWIW, until java 7 comes along, its really easiest to just use a
> 'closure' - an anonymous inner handling class. Something like:
>
> try {
>     InputStream in = getStream();
>     SafeIO.go(in, new SafeIO.Input() { public void handle(InputStream
> in) {
>         //do stuff here
>     }});} catch ( IOException e ) {
>
>     //handle exceptions here.
>
> }
>
> you'll need to roll SafeIO yourself, include a bunch of interfaces,
> and matching 'go' methods for each type of resource (InputStream,
> OutputStream, Reader, Writer...) - but its still easier to read than
> the alternative.

I like this approach -- see below for my implementation of SafeIO
based on this.  This only works for Closeables, and the code
being wrapped can't throw any check exceptions except IOException.

// usage:
OutputStream os = ...
SafeIO.go(os, new SafeIO.Handler<OutputStream>() {
    public void handle(OutputStream os) throws IOException {
        // do stuff here
    }
});

public class SafeIO {

    public interface Handler<C extends Closeable> {
        public void handle(C closeable) throws IOException;
    }

    public static<C extends Closeable> void go(C closeable, Handler<C>
handler)
        throws IOException
    {
        try {
            handler.handle(closeable);
        } catch (Throwable e) {
            try {
                closeable.close();
            } catch (Throwable ignore) {
            }
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            } else if (e instanceof Error) {
                throw (Error) e;
            } else {
                throw (IOException) e;  // only possibility left
            }
        }
        closeable.close();
    }

}

>
> On Jun 4, 3:54 am, RogerV <[email protected]> wrote:
>
>
>
> > On OutputStream I do a flush() explicitly in the try block instead of
> > relying on close() to do the buffer flush.
>
> > The finally() block then does the close() and swallows the close()
> > exception.
>
> > If there was a problem on the flush() then the exception will be
> > caught in the catch() block and will be plain to see without having
> > been swallowed.
>
> > --Roger
>
> > On Jun 2, 10:07 pm, Mark Hibberd <[email protected]> wrote:
>
> > > On Wed, Jun 3, 2009 at 12:55 PM, Christian Catchpole
>
> > > <[email protected]> wrote:
>
> > > > Yeah, this can be a problem.  Perhaps the neatest way is to do
> > > > something like this..  use a static helper which eats the exception.
>
> > > > OutputStream os = new BlahOutputStream();
> > > > try {
> > > >   // do stuff hyar, hyar and hyar..
> > > >   os.write( stuff );
> > > > } finally {
> > > >   StreamHelperThingy.closeDontThrow(os);
> > > > }
>
> > > That is probably ok for an InputStream but it is definitely not  for
> > > an OutputStream. If there is buffering going on, flush will get called
> > > via the close method, triggering an exception and your data would not
> > > have been written. With your example you would never find that out.
>
> > > You only want to swallow an exception thrown from close if there was
> > > an exception from the try. I would recommend writing something like:
>
> > > class WithOutputStream {
> > >   public static <T> T blah(UsingOutputStream<T> action) {
> > > OutputStream os = new BlahOutputStream();
> > >   }
>
> > > }
>
> > > class
>
> > > > On Jun 3, 10:01 am, Tim <[email protected]> wrote:
> > > >> In Joshua Bloch's Automatic Resource Management proposal
> > > >> (http://docs.google.com/Doc?id=ddv8ts74_3fs7483dp) for project Coin he
> > > >> wrote:
>
> > > >>     Even the "correct" idioms for manual resource management are
> > > >> deficient:
> > > >>     if an exception is thrown in the try block, and another when
> > > >> closing the
> > > >>     resource in the finally block, the second exception supplants the
> > > >>     first, making it difficult to determine the real cause of the
> > > >> trouble.
> > > >>     In other words, by responsibly closing your resource even during
> > > >> some
> > > >>     catastrophic event, you can actually erase all record of the
> > > >> event,
> > > >>     resulting in many wasted hours of debugging. While it is possible
> > > >> to
> > > >>     write code to suppress the second exception in favor of the first,
> > > >>     virtually no one does, as it is just too verbose. This is not a
> > > >>     theoretical problem; it has greatly complicated the debugging of
> > > >> large
> > > >>     systems.
>
> > > >> I just encountered this problem: Some code threw an exception creating
> > > >> a zip.
> > > >> The ZipOutputStream was closed in a finally block and the real
> > > >> exception
> > > >> was replaced by one complaining that there were no entries in the zip.
>
> > > >> Does anyone do the "right" thing?  What are the best idioms or helper
> > > >> methods/classes to do this?- Hide quoted text -
>
> - Show quoted text -
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to