A Handle is a Haskell runtime-managed value representing an open file connection and its access, position, and buffering properties. System.IO provides operations for opening, reading, writing, seeking, flushing, and closing handles. Standard input, output, and error are already-open handles. section 14.1.1
Choose an IOMode when opening a handle with openFile:
- ReadMode opens a file for reading. section 14.1.1
- WriteMode opens or creates a file and truncates existing contents. section 14.1.1
- AppendMode opens or creates a file and positions writing at its end. section 14.1.1
- ReadWriteMode opens or creates a file for both operations without truncating it. section 14.1.1
Handles maintain mutable operational state. Buffering controls when output reaches the filesystem: NoBuffering writes immediately, LineBuffering flushes at newlines, and BlockBuffering accumulates a block. Use hFlush or hClose to flush explicitly. Seekable handles also track a position that hTell reads and hSeek changes. section 14.1.2
Write, read, and close a file
In GHCi, import System.IO, open test.txt with WriteMode, write a line using hPutStrLn, and close it with hClose. Reopen it with ReadMode, retrieve the line with hGetLine, and close the second handle. Always close handles deliberately rather than relying on garbage collection. section 14.2
ghci> import System.IO ghci> h <- openFile "test.txt" WriteMode ghci> hTell h 0 ghci> hPutStr h "Hello" ghci> hTell h 5 ghci> hPutStr h " " ghci> hTell h 6 ghci> hPutStr h "World" ghci> hTell h 11 ghci> hSeek h AbsoluteSeek 6 ghci> hPutStr h "Haskell" ghci> hClose h
Inspect how hTell advances after writes and how hSeek moves to an earlier position before overwriting file contents. section 14.1.2
For byte-oriented work, combine handles with Data.ByteString. BS.hGet reads up to a requested number of bytes without failing at end of file, making handles suitable for inspecting file signatures. Use bracket when acquisition and release must remain safe if an exception occurs. section 14.2 section 14.5
