我正在用Haskell编写一个应用程序,如果readFile或writeFile失败,我希望向用户显示一条有意义的错误消息。目前,我正在用IOError捕获Control.Exception.tryJust,并将它们转换为人类可读的文本。
然而,我在找出应该捕获哪些错误以及如何从它们中提取信息时遇到了困难。例如,假设"/bin“是一个目录,而"/bin/ls”是一个文件,则readFile "/bin"和readFile "/bin/ls/asdf"都提供“不适当的类型”,但是(我认为)它们是不同的错误。对于第一个文件,我可以通过处理目录中的每个文件来恢复,而第二个文件更像是“不存在”类型的错误。
与前面的例子相比,似乎没有一种可移植的方法来捕获“不适当的类型”错误。看看GHC.IO.Exception,InappropriateType被标记为GHC--所以我不能只在ioeGetErrorType上匹配模式。我可以在ioeGetErrorString上进行模式匹配,但我不确定这些字符串在不同的平台、编译器、区域设置等之间是否总是相同的。
总括而言,我的问题是:
readFile/writeFile应该捕获哪些异常InappropriateType。更新:
基于@ErikR的回答,我使用以下Haskell程序查看GHC.IO.Exception.IOException字段:
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发布于 2016-06-29 02:11:53
在OS下,如果您使用openFile,然后是hGetContents,而不是readFile,那么您所提到的情况就会有不同的异常。
openFile "/bin/ls/asdf" ...将抛出“没有这样的文件或目录”异常,而openFile "/bin" ...将抛出“不适当的类型”。
在Linux下,两个打开的调用都会引发“不适当的类型”异常。但是,您可以通过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会话:
*Main> bar "/bin"
errno: Nothing
description: is a directory
*Main> bar "/bin/ls/asd"
errno: Just 20
description: Not a directory每个异常都有自己的结构。IOException的定义可以找到这里。
要将字段访问器引入范围,您需要导入GHC.IO.Exception。
正如@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 = Nothinghttps://stackoverflow.com/questions/38080021
复制相似问题