openReader :: String -> IO BufferedReader
Frege basics: File I/O
Intro
All examples are based on IO.fr
module functions. You can find them
Here.
Reading
We’ll be using the openReader function. It creates a BufferedReader from a given file path in the form of a String.
The first example reads a file getting a list of lines out of it:
readLines :: String -> IO [String]
readLines path = do
reader <- openReader path
reader.getLines
Here you have a shorter version:
readLines' :: String -> IO [String]
readLines' path = openReader path >>= _.getLines
Here we were using the placeholder notation _.XXX to
avoid creating intermediate values.
|
But bear in mind that if you give a wrong path the function call will raise an error. Here is an example returning an empty list in case the file doesn’t exists.
safeReadLines :: String -> IO [String]
safeReadLines path = openReader path >>= _.getLines
`catch` (\(e :: FileNotFoundException) -> return [])
Writing
As opposed to openReader there is a openWriter to write to a file. The openWriter and appendWriter functions return a PrintWriter instance. Lets see how can we use them. In the first example I’m setting the content of a file.
writeStringToFile :: String -> String -> IO ()
writeStringToFile path line = do
writer <- openWriter path (1)
writer.print line (2)
writer.flush (3)
1 | Getting the PrintWriter instance |
2 | Writing to file |
3 | Flushing to reflect the changes |
flushing is important when writing to a file. |
But most of the time we would like to append information to a file. The following example does exactly that.
appendLine :: String -> String -> IO ()
appendLine path line = do
writer <- appendWriter path (1)
writer.println line (2)
writer.flush (3)
1 | Getting the PrintWriter instance |
2 | Appending content to a file |
3 | Flushing to reflect the changes |