我正在尝试读取当前目录中每个文件的第一行:
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)
我想检测并避免此类文件,然后继续下一个文件。
答案 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]来自动为您工作。