io-streams-1.1.4.3: src/System/IO/Streams/File.hs
-- | Input and output streams for files.
--
-- The functions in this file use \"with*\" or \"bracket\" semantics, i.e. they
-- open the supplied 'FilePath', run a user computation, and then close the
-- file handle. If you need more control over the lifecycle of the underlying
-- file descriptor resources, you are encouraged to use the functions from
-- "System.IO.Streams.Handle" instead.
module System.IO.Streams.File
( -- * File conversions
withFileAsInput
, withFileAsInputStartingAt
, unsafeWithFileAsInputStartingAt
, withFileAsOutput
, withFileAsOutputExt
) where
------------------------------------------------------------------------------
import Control.Monad (unless)
import Data.ByteString (ByteString)
import Data.Int (Int64)
import System.IO (BufferMode (NoBuffering), IOMode (ReadMode, WriteMode), SeekMode (AbsoluteSeek), hSeek, hSetBuffering, withBinaryFile)
------------------------------------------------------------------------------
import System.IO.Streams.Handle (handleToInputStream, handleToOutputStream)
import System.IO.Streams.Internal (InputStream, OutputStream)
------------------------------------------------------------------------------
-- | @'withFileAsInput' name act@ opens the specified file in \"read mode\" and
-- passes the resulting 'InputStream' to the computation @act@. The file will
-- be closed on exit from @withFileAsInput@, whether by normal termination or
-- by raising an exception.
--
-- If closing the file raises an exception, then /that/ exception will be
-- raised by 'withFileAsInput' rather than any exception raised by @act@.
withFileAsInput :: FilePath -- ^ file to open
-> (InputStream ByteString -> IO a) -- ^ function to run
-> IO a
withFileAsInput = withFileAsInputStartingAt 0
------------------------------------------------------------------------------
-- | Like 'withFileAsInput', but seeks to the specified byte offset before
-- attaching the given file descriptor to the 'InputStream'.
withFileAsInputStartingAt
:: Int64 -- ^ starting index to seek to
-> FilePath -- ^ file to open
-> (InputStream ByteString -> IO a) -- ^ function to run
-> IO a
withFileAsInputStartingAt idx fp m = withBinaryFile fp ReadMode go
where
go h = do
unless (idx == 0) $ hSeek h AbsoluteSeek $ toInteger idx
handleToInputStream h >>= m
------------------------------------------------------------------------------
-- | Like 'withFileAsInputStartingAt', except that the 'ByteString' emitted by
-- the created 'InputStream' may reuse its buffer. You may only use this
-- function if you do not retain references to the generated bytestrings
-- emitted.
unsafeWithFileAsInputStartingAt
:: Int64 -- ^ starting index to seek to
-> FilePath -- ^ file to open
-> (InputStream ByteString -> IO a) -- ^ function to run
-> IO a
unsafeWithFileAsInputStartingAt = withFileAsInputStartingAt
------------------------------------------------------------------------------
-- | Open a file for writing and attaches an 'OutputStream' for you to write
-- to. The file will be closed on error or completion of your action.
withFileAsOutput
:: FilePath -- ^ file to open
-> (OutputStream ByteString -> IO a) -- ^ function to run
-> IO a
withFileAsOutput f = withFileAsOutputExt f WriteMode NoBuffering
------------------------------------------------------------------------------
-- | Like 'withFileAsOutput', but allowing you control over the output file
-- mode and buffering behaviour.
withFileAsOutputExt
:: FilePath -- ^ file to open
-> IOMode -- ^ mode to write in
-> BufferMode -- ^ should we buffer the output?
-> (OutputStream ByteString -> IO a) -- ^ function to run
-> IO a
withFileAsOutputExt fp iomode buffermode m = withBinaryFile fp iomode $ \h -> do
hSetBuffering h buffermode
handleToOutputStream h >>= m