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.