Как узнать, является ли файл двоичным - PullRequest
0 голосов
/ 19 мая 2019

Я пытаюсь прочитать текст всех файлов в папке со следующим кодом:

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 Ответ

1 голос
/ 23 мая 2019

Определение двоичного кода довольно расплывчато, но при условии, что вы имеете в виду контент, который не является допустимым текстом UTF-8.

Вы должны использовать toString в Data.ByteString.UTF8, который заменяет символы, отличные от UTF-8, на замену, но не приводит к ошибке с ошибкой.

Преобразование вашего примера для использования UTF-8 ByteStrings:

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 (пробел).

...