Tôi đang viết một ứng dụng trong Haskell và muốn hiển thị thông báo lỗi có ý nghĩa cho người dùng nếu readFile
hoặc writeFile
không thành công. Tôi hiện đang tìm kiếm IOError
s với Control.Exception.tryJust
và chuyển đổi chúng thành văn bản có thể đọc được.Cách đúng để xử lý ngoại lệ readFile và writeFile
Tuy nhiên, tôi đang gặp khó khăn trong việc tìm ra lỗi nào tôi nên nắm bắt và cách trích xuất thông tin từ chúng. Ví dụ, giả sử "/ bin" là một thư mục và "/ bin/ls" là một tệp, readFile "/bin"
và readFile "/bin/ls/asdf"
cả hai đều cung cấp "loại không phù hợp" nhưng (theo ý kiến của tôi) chúng là các lỗi khác nhau. Trong trường hợp đầu tiên, tôi có thể phục hồi bằng cách xử lý từng tệp trong thư mục, trong khi thứ hai giống như loại lỗi "không tồn tại".
Liên quan đến ví dụ trước, có vẻ như đó không phải là cách di chuyển các lỗi "loại không phù hợp". Nhìn vào GHC.IO.Exception, InappropriateType
được đánh dấu chỉ GHC nên tôi không thể chỉ khớp mẫu trên ioeGetErrorType
. Tôi có thể phù hợp với mô hình trên ioeGetErrorString
nhưng tôi không chắc chắn nếu những chuỗi luôn luôn giống nhau trên nhiều nền tảng khác nhau, trình biên dịch, miền địa phương vv
Nói tóm lại, câu hỏi của tôi là:
- Những trường hợp ngoại lệ nên tôi bị bắt cho
readFile
/writeFile
? - Khi tôi có ngoại lệ, tôi nên làm thế nào để trích xuất thông tin từ nó?
- Có cách nào cầm tay để bắt các ngoại lệ chỉ áp dụng cho GHC chẳng hạn như
InappropriateType
?
Cập nhật:
Dựa trên câu trả lời @ ErikR của tôi là nhìn vào các lĩnh vực GHC.IO.Exception.IOException
với chương trình Haskell sau:
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
]
Sản lượng trên Debian Sid GNU/Linux với GHC 7.10.3 là:
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
Tôi không lạc quan về ngoại lệ "di động" với trạng thái hiện tại của cơ sở hạ tầng Haskell. Chúng tôi đã bị mắc kẹt trong một chế độ biên dịch cho một số năm. Đây là hy vọng rằng những thay đổi sớm. – dfeuer