readFile and closing a file

Say I acquire a text by readFile, feed it to a lazy parser and the parser stops reading because of a parse error. After the parser error I won't fetch more characters from the text file, but readFile does not get to know that and cannot close the file. Actually, when encountering a parser error I could read the remaining characters from the file in order to let readFile close the file eventually, but this sounds rather inefficient. So, what is the right way to go, or do I have to stay away from readFile (and maybe unsafeInterleaveIO at all)?

Hi Henning, I tend to use openFile, hGetContents, hClose - your initial readFile like call should be openFile/hGetContents, which gives you a lazy stream, and on a parse error call hClose. Thanks Neil
-----Original Message----- From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Henning Thielemann Sent: 17 September 2008 12:31 pm To: Haskell Cafe Subject: [Haskell-cafe] readFile and closing a file
Say I acquire a text by readFile, feed it to a lazy parser and the parser stops reading because of a parse error. After the parser error I won't fetch more characters from the text file, but readFile does not get to know that and cannot close the file. Actually, when encountering a parser error I could read the remaining characters from the file in order to let readFile close the file eventually, but this sounds rather inefficient. So, what is the right way to go, or do I have to stay away from readFile (and maybe unsafeInterleaveIO at all)? _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
============================================================================== Please access the attached hyperlink for an important electronic communications disclaimer: http://www.credit-suisse.com/legal/en/disclaimer_email_ib.html ==============================================================================

On Wed, 17 Sep 2008, Mitchell, Neil wrote:
Hi Henning,
I tend to use openFile, hGetContents, hClose - your initial readFile like call should be openFile/hGetContents, which gives you a lazy stream, and on a parse error call hClose.
Yes, this seems to be the right way. This weakness should be mentioned in the docs of readFile. In production code, you cannot rely on a garbage collector to close the file, because you might want to open a file for writing after you have processed it with readFile, and there is warranty that the file is already closed then.

On Thu, Sep 18, 2008 at 05:38:51PM +0200, Henning Thielemann wrote:
On Wed, 17 Sep 2008, Mitchell, Neil wrote:
I tend to use openFile, hGetContents, hClose - your initial readFile like call should be openFile/hGetContents, which gives you a lazy stream, and on a parse error call hClose.
Yes, this seems to be the right way. This weakness should be mentioned in the docs of readFile. In production code, you cannot rely on a garbage collector to close the file, because you might want to open a file for writing after you have processed it with readFile, and there is warranty that the file is already closed then.
Ah, so you must be concerned about windows systems? Yes, on windows systems it's definitely best to never to lazy IO. On non-windows file systems, unless you're planning on opening thousands of files, relying on the garbage collector is fine. David

On Wed, 17 Sep 2008, Mitchell, Neil wrote:
I tend to use openFile, hGetContents, hClose - your initial readFile like call should be openFile/hGetContents, which gives you a lazy stream, and on a parse error call hClose.
I could use a function like withReadFile :: FilePath -> (Handle -> IO a) -> IO a withReadFile name action = bracket openFile hClose ... Then, if 'action' fails, the file can be properly closed. However, there is still a problem: Say, 'action' is a parser which produces a data structure lazily. Then further processing of that data structure of type 'a' may again stop before completing the whole structure, which would also leave the file open. We have to force users to do all processing within 'action' and to only return strict values. But how to do this?

On Wed, Sep 17, 2008 at 01:31:26PM +0200, Henning Thielemann wrote:
Say I acquire a text by readFile, feed it to a lazy parser and the parser stops reading because of a parse error. After the parser error I won't fetch more characters from the text file, but readFile does not get to know that and cannot close the file. Actually, when encountering a parser error I could read the remaining characters from the file in order to let readFile close the file eventually, but this sounds rather inefficient. So, what is the right way to go, or do I have to stay away from readFile (and maybe unsafeInterleaveIO at all)?
Eventually the garbage collector should close the file, I believe. David

On Wed, Sep 17, 2008 at 6:21 AM, David Roundy
Eventually the garbage collector should close the file, I believe.
That's true, but "eventually" could be long enough to mean "never" in practice. It's safest to assume that finalizers will not run at all, never mind in a timely fashion.
participants (4)
-
Bryan O'Sullivan
-
David Roundy
-
Henning Thielemann
-
Mitchell, Neil