How to catch the decompress IOError?

gzip, haskell

Solution

You need to import Codec.Compression.Zlib.Internal. Note in particular the section titled “Low-level API to get explicit error reports”.

You will want to use something like this (note untested):

import qualified Codec.Compression.Zlib.Internal as Z
import Control.Arrow (right)

decompressWithoutExceptions :: L.ByteString -> Either Z.DecompressError L.ByteString
decompressWithoutExceptions = finalise
                            . Z.foldDecompressStream cons nil err
                            . Z.decompressWithErrors Z.gzipFormat Z.defaultDecompressParams
  where err errorCode errorString = Left errorCode
        nil = Right []
        cons chunk = right (chunk :)
        finalise = right L.fromChunks

(I presume you have imported Data.ByteString.Lazy qualified as L.)

Problem

I wrote this code snippet to read a file that may be compressed: ``` import Codec.Compression.GZip import IO -- using IO.try read file = do let f = L.readFile file let c = fmap decompress $ f unzipped <- try c case unzipped of Right b -> return b Left _ -> f ``` It compiles just fine, but it seems that this is no valid way to handle uncompressed files. Running the code on a compressed file works nice, but a uncompressed file fails with an exception: ``` *** Exception: Codec.Compression.Zlib: incorrect header check ``` Any idea on how to make this possible?

Original source