如何查找文件是否为二进制文件

时间:2019-05-19 12:58:31

标签: file haskell binaryfiles

我正在尝试使用以下代码读取文件夹中所有文件的文本:

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)

如何检查文件句柄本身中的字符?

1 个答案:

答案 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(空格字符)的代码点。