[Haskell-cafe] semi-closed handles

Ryan Ingram ryani.spam at gmail.com
Tue Apr 15 03:37:20 EDT 2008


I usually use something like this instead:

hStrictGetContents :: Handle -> IO String
hStrictGetContents h = do
    s <- hGetContents h
    length s `seq` hClose h
    return s

This guarantees the following:
1) The whole file is read before hStrictGetContents exits (could be
considered bad, but usually it's The Right Thing)
2) You guarantee that you don't leak file handles (good benefit!)

A slightly better version:

import qualified Data.ByteString.Char8 as B

hStrictGetContents :: Handle -> IO String
hStrictGetContents h = do
    bs <- B.hGetContents h
    hClose h -- not sure if this is required; ByteString documentation
isn't clear.
    return $ B.unpack bs -- lazy unpack into String

This saves a ton of memory for big reads; a String is ~12 bytes per
character, this is only 1 byte per character + fixed overhead.  Then,
assuming the function consuming the String doesn't leak, you'll end up
with a much smaller space requirement.

  -- ryan

2008/4/14 Abhay Parvate <abhay.parvate at gmail.com>:
> Thanks! I was worried about how/where would I place hClose!
>
>
>
> On Mon, Apr 14, 2008 at 10:58 PM, Brent Yorgey <byorgey at gmail.com> wrote:
> >
> >
> > 2008/4/14 Abhay Parvate <abhay.parvate at gmail.com>:
> >
> >
> >
> >
> > > Hello,
> > >
> > > In describing the Handle type, the GHC documentation says (in the
> System.IO documentation):
> > >
> > >
> > > GHC note: a Handle will be automatically closed when the garbage
> collector detects that it has become unreferenced by the program. However,
> relying on this behaviour is not generally recommended: the garbage
> collector is unpredictable. If possible, use explicit an explicit hClose to
> close Handles when they are no longer required. GHC does not currently
> attempt to free up file descriptors when they have run out, it is your
> responsibility to ensure that this doesn't happen.
> > >
> > > But one cannot call hClose on Handles on which something like
> hGetContents has been called; it just terminates the character list at the
> point till which it has already read. Further the manual says that
> hGetContents puts the handle in the semi-closed state, and further,
> > >
> > >
> > > A semi-closed handle becomes closed:
> > >
> > > if hClose is applied to it;
> > > if an I/O error occurs when reading an item from the handle;
> > > or once the entire contents of the handle has been read. So do I safely
> assume here, according to the third point above, that it's fine if I do not
> call hClose explicitly as far as I am consuming all the contents returned by
> hGetContents?
> > >
> >
> >
> > Yes, not only is it fine, it's recommended!  Calling hClose explicitly on
> a handle after calling hGetContents is a sure way to introduce bugs.
> >
> > -Brent
> >
> >
>
>
> _______________________________________________
>  Haskell-Cafe mailing list
>  Haskell-Cafe at haskell.org
>  http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>


More information about the Haskell-Cafe mailing list