Q:

How to catch the decompress IOError?

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?

A:

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.)

