On Fri, Aug 23, 2013 at 12:21 AM, Remko Popma <remko.po...@gmail.com> wrote:
> And I just realized I addressed you by your last name in an earlier > message by mistake. Apologies! It's all good :) Gary > > > On Friday, August 23, 2013, Remko Popma wrote: > >> Thanks Gary! I think that's fine. >> It does look a bit verbose, perhaps we can make a Closer class in the >> helpers package with methods like this: >> >> public static void closeSilent(Closable closable) { >> try { >> if (in != null) { >> in.close(); >> } >> } catch (final Exception ignored) { >> // ignored >> } >> } >> >> public static void closeWarn(Closable closable, String name) { >> try { >> if (in != null) { >> in.close(); >> } >> } catch (final Exception ignored) { >> LOGGER.warn("Could not close resource: " + name); >> } >> } >> >> >> On Friday, August 23, 2013, Gary Gregory wrote: >> >>> On Thu, Aug 22, 2013 at 10:02 PM, Gary Gregory >>> <garydgreg...@gmail.com>wrote: >>> >>> On Thu, Aug 22, 2013 at 8:31 PM, Remko Popma <remko.po...@gmail.com>wrote: >>> >>> Sorry if I was unclear. What if creating the Reader fails after the >>> InputStream was created? Then there is no reader object to call close on... >>> In not sure that protecting against a NPE is enough, so I want to close the >>> InputStream in the finally clause. Closing the Reader as well is fine but >>> optional IMO. >>> >>> >>> OK, I can see that. >>> >>> Since each JRE can implement the reader differently, is should also be >>> closed. This would be easier in Java 7 with a try-with-resources, so now I >>> have: >>> >>> >>> Arg, slippery keys. I mean: >>> >>> private String readContents(final URI uri, final Charset charset) throws >>> IOException { >>> InputStream in = null; >>> Reader reader = null; >>> try { >>> in = uri.toURL().openStream(); >>> reader = new InputStreamReader(in, charset); >>> final StringBuilder result = new StringBuilder(TEXT_BUFFER); >>> final char[] buff = new char[PAGE]; >>> int count = -1; >>> while ((count = reader.read(buff)) >= 0) { >>> result.append(buff, 0, count); >>> } >>> return result.toString(); >>> } finally { >>> try { >>> if (in != null) { >>> in.close(); >>> } >>> } catch (final Exception ignored) { >>> // ignored >>> } >>> try { >>> if (reader != null) { >>> reader.close(); >>> } >>> } catch (final Exception ignored) { >>> // ignored >>> } >>> } >>> } >>> >>> Is there a better way to make sure all allocated resources are freed? >>> The Reader contract is clear: >>> >>> /** >>> * Closes the stream and releases any system resources associated >>> with >>> * it. Once the stream has been closed, further read(), ready(), >>> * mark(), reset(), or skip() invocations will throw an IOException. >>> * Closing a previously closed stream has no effect. >>> * >>> * @exception IOException If an I/O error occurs >>> */ >>> abstract public void close() throws IOException; >>> >>> So that would be enough but as you point out, building the reader might >>> blow up. >>> >>> In my JRE (Oracle) I see: >>> >>> public InputStreamReader(InputStream in, Charset cs) { >>> super(in); >>> if (cs == null) >>> throw new NullPointerException("charset"); >>> sd = StreamDecoder.forInputStreamReader(in, this, cs); >>> } >>> >>> and StreamDecoder is internal code to Oracle so who knows what it does. >>> >>> So... the InputStream should also be closed: >>> >>> /** >>> * Closes this input stream and releases any system resources >>> associated >>> * with the stream. >>> * >>> * <p> The <code>close</code> method of <code>InputStream</code> does >>> * nothing. >>> * >>> * @exception IOException if an I/O error occurs. >>> */ >>> public void close() throws IOException {} >>> >>> but in this case the behavior of closing again, is undefined, so it >>> should happen first, before closing the reader, whose contract states that >>> it can handled being closed many times. >>> >>> Can this be done better? >>> >>> Gary >>> >>> Gary >>> >>> >>> >>> >>> On Friday, August 23, 2013, Gary Gregory wrote: >>> >>> Hi Remko, >>> >>> I tried it both ways and it just looks simpler to read this way. The >>> reader passes the close to its wrapped stream. In both cases, you need to >>> close the reader (or the stream) and protect that close with a null guard. >>> >>> Gary >>> >>> >>> On Thu, Aug 22, 2013 at 7:10 PM, Remko Popma <remko.po...@gmail.com>wrote: >>> >>> -- >>> E-Mail: garydgreg...@gmail.com | ggreg...@apache.org >>> Java Persistence with Hibernate, Second >>> Edition<http://www.manning.com/bauer3/> >>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>> Spring Batch in Action <http://www.manning.com/templier/> >>> Blog: http://garygregory.wordpress.com >>> Home: http://garygregory.com/ >>> Tweet! http://twitter.com/GaryGregory >>> >> -- E-Mail: garydgreg...@gmail.com | ggreg...@apache.org Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> Spring Batch in Action <http://www.manning.com/templier/> Blog: http://garygregory.wordpress.com Home: http://garygregory.com/ Tweet! http://twitter.com/GaryGregory