我正在尝试使用以下代码读取文件夹中所有文件的文本:
readALine :: FilePath -> IO ()
readALine fname = do
putStr . show $ "Filename: " ++ fname ++ "; "
fs <- getFileSize fname
if fs > 0 then do
hand <- openFile fname ReadMode
fline <- hGetLine hand
hClose hand
print $ "First line: " <> fline
else return ()
但是,其中一些文件是二进制文件。如何查找给定文件是否为二进制文件?我在https://hoogle.haskell.org/?hoogle=binary%20file
中找不到任何此类功能感谢您的帮助。
编辑:二进制表示文件具有不可打印的字符。我不确定这些文件的专有名词。
我安装了UTF8字符串并修改了代码:
readALine :: FilePath -> IO ()
readALine fname = do
putStr . show $ "Filename: " ++ fname ++ "; "
fs <- getFileSize fname
if fs > 0 then do
hand <- openFile fname ReadMode
fline <- hGetLine hand
hClose hand
if isUTF8Encoded (unpack fline) then do
print $ "Not binary file."
print $ "First line: " <> fline
else return ()
else return ()
现在它可以工作,但是遇到“二进制”可执行文件(称为esync.x)时,hGetLine hand
表达式会出现错误:
"Filename: ./esync.x; "firstline2.hs: ./esync.x: hGetLine: invalid argument (invalid byte sequence)
如何检查文件句柄本身中的字符?
答案 0 :(得分:1)
二进制的定义非常模糊,但是假设您的意思是无效的UTF-8文本。
您应在toString
中使用Data.ByteString.UTF8
,以将非UTF-8字符替换为替换字符,但不会因错误而失败。
将示例转换为使用UTF-8 ByteString:
import Data.Monoid
import System.IO
import System.Directory
import qualified Data.ByteString as B
import qualified Data.ByteString.UTF8 as B
readALine :: FilePath -> IO ()
readALine fname = do
putStr . show $ "Filename: " ++ fname ++ "; "
fs <- getFileSize fname
if fs > 0 then do
hand <- openFile fname ReadMode
fline <- B.hGetLine hand
hClose hand
print $ "First line: " <> B.toString fline
else return ()
该代码不会在二进制文件上失败,但实际上并没有检测到二进制文件内容。如果要检测二进制文件,请在数据中寻找B.replacement_char
。要检测不可打印的字符,您可能还会查找小于32(空格字符)的代码点。