Like in several other parts of the I/O library, functions that implicitly use a standard stream have a counterpart in System.IO
that performs the same job, but with an extra parameter at the left, of type Handle
, that represents the stream being handled. For instance, getLine :: IO String
has a counterpart hGetLine :: Handle -> IO String
.
import System.IO( Handle, FilePath, IOMode( ReadMode ),
openFile, hGetLine, hPutStr, hClose, hIsEOF, stderr )
import Control.Monad( when )
dumpFile :: Handle -> FilePath -> Integer -> IO ()
dumpFile handle filename lineNumber = do -- show file contents line by line
end <- hIsEOF handle
when ( not end ) $ do
line <- hGetLine handle
putStrLn $ filename ++ ":" ++ show lineNumber ++ ": " ++ line
dumpFile handle filename $ lineNumber + 1
main :: IO ()
main = do
hPutStr stderr "Type a filename: "
filename <- getLine
handle <- openFile filename ReadMode
dumpFile handle filename 1
hClose handle
Contents of file example.txt
:
This is an example.
Hello, world!
This is another example.
Input:
Type a filename: example.txt
Output:
example.txt:1: This is an example.
example.txt:2: Hello, world!
example.txt:3: This is another example