Temporary Files And Directories in Haskell
Throughout program execution, we often want to create data that isn’t needed after the program exits. Temporary files and directories are useful for this purpose since they don’t pollute the file system over time.
import System.IO
import System.Directory
import System.FilePath
import Control.Exception (catch, SomeException)
main :: IO ()
main = do
The easiest way to create a temporary file in Haskell is by using openTempFile
. It creates a file and opens it for reading and writing. We provide getTemporaryDirectory
as the first argument to create the file in the default temporary location for our OS.
tempDir <- getTemporaryDirectory
(tempFile, tempHandle) <- openTempFile tempDir "sample"
Display the name of the temporary file. On Unix-based OSes the directory will likely be /tmp
. The file name starts with the prefix given as the second argument to openTempFile
and the rest is chosen automatically to ensure that concurrent calls will always create different file names.
putStrLn $ "Temp file name: " ++ tempFile
Clean up the file after we’re done. The OS is likely to clean up temporary files by itself after some time, but it’s good practice to do this explicitly.
-- We'll use 'finally' to ensure the file is removed even if an exception occurs
flip finally (removeFile tempFile) $ do
We can write some data to the file.
hPutStr tempHandle "\x01\x02\x03\x04"
hClose tempHandle
If we intend to create many temporary files, we may prefer to create a temporary directory. createTempDirectory
is similar to openTempFile
, but it returns a directory name rather than an open file.
tempDirPath <- createTempDirectory tempDir "sampledir"
putStrLn $ "Temp dir name: " ++ tempDirPath
-- Clean up the directory after we're done
flip finally (removeDirectoryRecursive tempDirPath) $ do
Now we can synthesize temporary file names by prefixing them with our temporary directory.
let fname = tempDirPath </> "file1"
writeFile fname "\x01\x02"
Here’s how you might run this program:
$ runhaskell temporary-files-and-directories.hs
Temp file name: /tmp/sampleXXXXXX
Temp dir name: /tmp/sampledirXXXXXX
In this Haskell version, we use System.IO
for file operations, System.Directory
for directory operations, and System.FilePath
for path manipulation. We also use Control.Exception
for exception handling to ensure proper cleanup of resources.
The finally
function is used to ensure that cleanup actions (like removing temporary files and directories) are performed even if an exception occurs during the main execution.
Note that unlike the original example, Haskell’s openTempFile
and createTempDirectory
functions automatically generate unique suffixes for the file and directory names, so we don’t need to provide a pattern for this.