gpt4 book ai didi

haskell - 处理 readFile 和 writeFile 异常的正确方法

转载 作者:行者123 更新时间:2023-12-04 15:32:07 25 4
gpt4 key购买 nike

我正在用 Haskell 编写一个应用程序,如果 readFile,我想向用户显示一条有意义的错误消息。或 writeFile失败。我目前正在抓 IOErrorControl.Exception.tryJust并将它们转换为人类可读的文本。

但是,我无法确定应该捕获哪些错误以及如何从中提取信息。例如,假设“/bin”是目录,“/bin/ls”是文件,readFile "/bin"readFile "/bin/ls/asdf"两者都给出“不适当的类型”,但(在我看来)它们是不同的错误。在第一个的情况下,我可以通过处理目录中的每个文件来恢复,而第二个更像是“不存在”类型的错误。

关于前面的示例,似乎没有一种可移植的方法来捕获“不适当的类型”错误。看GHC.IO.Exception , InappropriateType被标记为 GHC-only 所以我不能只在 ioeGetErrorType 上进行模式匹配.我可以在 ioeGetErrorString 上进行模式匹配但我不确定这些字符串在不同的平台、编译器、语言环境等中是否总是相同的。

总之,我的问题是:

  • 我应该为 readFile 捕获哪些异常?/writeFile ?
  • 一旦出现异常,我应该如何从中提取信息?
  • 是否有一种可移植的方式来捕获仅 GHC 的异常,例如 InappropriateType ?

  • 更新:

    根据@ErikR 的回答,我正在查看 GHC.IO.Exception.IOException 的字段使用以下 Haskell 程序:
    import Control.Exception (try)
    import GHC.IO.Exception (IOException(..))
    import qualified Data.ByteString as B


    main :: IO ()
    main = do
    try (readFile "/nonexistent") >>= printException
    try (writeFile "/dev/full" " ") >>= printException
    try (readFile "/root") >>= printException
    try (readFile "/bin") >>= printException
    try (writeFile "/bin" "") >>= printException
    try (readFile "/bin/ls/asdf") >>= printException
    try (writeFile "/bin/ls/asdf" "") >>= printException
    try (B.readFile "/dev/null") >>= printException

    -- I have /media/backups mounted as read-only. Substitute your own read-only
    -- filesystem for this one
    try (writeFile "/media/backups/asdf" "") >>= printException

    printException :: Either IOError a -> IO ()
    printException (Right _) = putStrLn "No exception caught"
    printException (Left e) = putStrLn $ concat [ "ioe_filename = "
    , show $ ioe_filename e
    , ", ioe_description = "
    , show $ ioe_description e
    , ", ioe_errno = "
    , show $ ioe_errno e
    ]

    使用 GHC 7.10.3 的 Debian Sid GNU/Linux 上的输出是:
    ioe_filename = Just "/nonexistent", ioe_description = "No such file or directory", ioe_errno = Just 2
    ioe_filename = Just "/dev/full", ioe_description = "No space left on device", ioe_errno = Just 28
    ioe_filename = Just "/root", ioe_description = "Permission denied", ioe_errno = Just 13
    ioe_filename = Just "/bin", ioe_description = "is a directory", ioe_errno = Nothing
    ioe_filename = Just "/bin", ioe_description = "Is a directory", ioe_errno = Just 21
    ioe_filename = Just "/bin/ls/asdf", ioe_description = "Not a directory", ioe_errno = Just 20
    ioe_filename = Just "/bin/ls/asdf", ioe_description = "Not a directory", ioe_errno = Just 20
    ioe_filename = Just "/dev/null", ioe_description = "not a regular file", ioe_errno = Nothing
    ioe_filename = Just "/media/backups/asdf", ioe_description = "Read-only file system", ioe_errno = Just 30

    最佳答案

    1. Which exceptions should I be catching for readFile/writeFile?


    在 OS X 下,如果您使用 openFile后跟 hGetContents而不是 readFile那么对于您提到的情况,您将获得不同的异常(exception)情况。
    openFile "/bin/ls/asdf" ...将抛出“没有这样的文件或目录”异常,而 openFile "/bin" ...会抛出“不合适的类型”。

    在 Linux 下,两个 open 调用都会抛出“不适当的类型”异常。但是,您可以通过 ioe_errno 区分两者。和 ioe_description领域:
    import System.IO
    import GHC.IO.Exception
    import Control.Exception

    foo path = do
    h <- openFile path ReadMode
    hClose h

    show_ioe :: IOException -> IO ()
    show_ioe e = do
    putStrLn $ "errno: " ++ show (ioe_errno e)
    putStrLn $ "description: " ++ ioe_description e

    bar path = foo path `catch` show_ioe

    示例 ghci session :
    *Main> bar "/bin"
    errno: Nothing
    description: is a directory
    *Main> bar "/bin/ls/asd"
    errno: Just 20
    description: Not a directory

    1. Once I have an exception, how should I go about extracting information from it?


    每个异常都有自己的结构。 IOException 的定义见 here .

    要将字段访问器带入范围,您需要导入 GHC.IO.Exception .

    1. Is there a portable way of catching the GHC-only exceptions such as InappropriateType?


    正如@dfeuer 所说,出于所有实际目的,GHC 是目前唯一的 Haskell 实现。

    更新

    运行程序的结果。我没有包括最后一个结果,因为我没有一个只读文件系统来测试它,但我确信错误是一样的。
    ioe_filename = Just "/nonexistent", ioe_description = "No such file or directory", ioe_errno = Just 2
    ioe_filename = Just "/dev/full", ioe_description = "Permission denied", ioe_errno = Just 13
    ioe_filename = Just "/root", ioe_description = "is a directory", ioe_errno = Nothing
    ioe_filename = Just "/bin", ioe_description = "is a directory", ioe_errno = Nothing
    ioe_filename = Just "/bin", ioe_description = "Is a directory", ioe_errno = Just 21
    ioe_filename = Just "/bin/ls/asdf", ioe_description = "Not a directory", ioe_errno = Just 20
    ioe_filename = Just "/bin/ls/asdf", ioe_description = "Not a directory", ioe_errno = Just 20
    ioe_filename = Just "/dev/null", ioe_description = "not a regular file", ioe_errno = Nothing

    关于haskell - 处理 readFile 和 writeFile 异常的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38080021/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com