如何在Haskell中实现仅当文件不存在时才创建文件的功能
实现方案
方案1:GHC 8.10+ 内置通用方案
这是最易用的跨平台方案,内置异常处理逻辑,直接返回Handle,语义和C语言的open(O_CREAT|O_EXCL)完全一致:
import System.IO (Handle, openFileWith, WriteMode, OpenFileFlags(..), defaultOpenFileFlags) import Control.Exception (try) import System.IO.Error (IOError) -- 调用成功返回Handle,文件已存在/权限不足等情况返回IOError createFileIfNotExists :: FilePath -> IO (Either IOError Handle) createFileIfNotExists path = try $ openFileWith path WriteMode defaultOpenFileFlags { create = True -- 对应O_CREAT,文件不存在时创建 , exclusive = True -- 对应O_EXCL,文件已存在时报错 }
- 不需要自己处理底层竞态、系统调用异常等复杂逻辑,所有错误都会封装为标准
IOError抛出 - 支持Windows、Linux、macOS全平台
方案2:旧版GHC/类UNIX平台兼容方案
如果使用的是8.10之前版本的GHC,且仅需要支持类UNIX系统,可以用unix包实现:
import System.Posix.IO (openFd, OpenMode(WriteOnly), defaultFileFlags, exclusive, creat) import System.Posix.IO.ByteString (fdToHandle) import Control.Exception (try) import System.IO.Error (IOError) createFileIfNotExists :: FilePath -> IO (Either IOError Handle) createFileIfNotExists path = try $ do -- 0o644是默认文件权限,可按需修改 fd <- openFd path WriteOnly (Just 0o644) defaultFileFlags { creat = True , exclusive = True } fdToHandle fd
注意:该方案仅支持Linux、macOS等类UNIX系统,不兼容Windows。
补充说明
两个方案的底层都是直接调用操作系统的原子接口,不会出现多进程/多线程同时判断文件不存在、重复创建的竞态问题,完全满足需求。
内容的提问来源于stack exchange,提问作者dfeuer
相关产品推荐
相关产品推荐

