读取每个文件的第一行在二进制文件中中止

时间:2019-09-15 15:05:00

标签: haskell file-read

我正在尝试读取当前目录中每个文件的第一行:

import System.IO(IOMode(ReadMode), withFile, hGetLine)
import System.Directory (getDirectoryContents, doesFileExist, getFileSize)
import System.FilePath ((</>))
import Control.Monad(filterM)

readFirstLine :: FilePath -> IO String
readFirstLine fp = withFile fp ReadMode System.IO.hGetLine

getAbsoluteDirContents :: String -> IO [FilePath]
getAbsoluteDirContents dir = do
    contents <- getDirectoryContents dir
    return $ map (dir </>) contents

main :: IO ()
main = do
    -- get a list of all files & dirs
    contents <- getAbsoluteDirContents "."
    -- filter out dirs
    files <- filterM doesFileExist contents
    -- read first line of each file
    d <- mapM readFirstLine files
    print d

它正在编译并运行,但是在二进制文件中因以下错误而中止:

mysrcfile: ./aBinaryFile: hGetLine: invalid argument (invalid byte sequence)

我想检测并避免此类文件,然后继续下一个文件。

1 个答案:

答案 0 :(得分:0)

二进制文件是一个文件,其中包含无法解码为有效字符串的字节序列。但是,如果不检查二进制文件的内容,则二进制文件与文本文件没有什么不同。

使用“ E 更容易实现 A sk F 主动性比 P 发射更好(EAFP)”方法:我们尝试读取第一行,如果失败,则忽略输出。

import Control.Exception(catch, IOException)
import System.IO(IOMode(ReadMode), withFile, hGetLine)

readFirstLine :: FilePath -> IO (Maybe String)
readFirstLine fp = withFile fp ReadMode $
    \h -> (catch (fmap Just (hGetLine h))
        ((const :: a -> IOException -> a) (return Nothing)))

对于FilePath,这将返回IO (Maybe String)。如果我们运行IO (Maybe String),它将返回一个Just x的{​​{1}},如果可以读取该文件,则返回第一行;如果x被加密,则返回Nothing

然后我们可以利用catMaybes :: [Maybe a] -> [a]来获得IOException

Just x

或者您可以在mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b]中使用extra package [Hackage]来自动为您工作。

相关问题