Haskell - неверная последовательность байтов кодовой страницы

readFile "file.html"
"start of the file... *** Exception: file.html: hGetContents: invalid argument (invalid code page byte sequence)

Это файл UTF-8, созданный с помощью блокнота ++... как я могу прочитать файл в haskell?

Ответ 1

По умолчанию файлы читаются в локали системы, поэтому, если у вас есть файл с использованием нестандартного кодирования, вам нужно установить кодировку дескриптора файла самостоятельно.

foo = do
    handle <- openFile "file.html" ReadMode
    hSetEncoding handle utf8_bom
    contents <- hGetContents handle
    doSomethingWithContents
    hClose handle

должно начаться. Обратите внимание, что это не содержит обработки ошибок, тем лучше будет

import Control.Exception -- for bracket

foo = bracket
        (openFile "file.html" ReadMode >>= \h -> hSetEncoding h utf8_bom >> return h)
        hClose
        (\h -> hGetContents h >>= doSomething)

или

foo = withFile "file.html" ReadMode $
        \h -> do hSetEncoding h utf8_bom
                 contents <- hGetContents h
                 doSomethingWith contents

Ответ 2

Согласно этот сайт, ваши 6 байтов декодируются следующим образом:

EF BB BF -> ZERO WIDTH NO-BREAK SPACE (i.e. the BOM, although its not needed in UTF-8
C4 8D    -> LATIN SMALL LETTER C WITH CARON (what you said)
0D       -> CARRIAGE RETURN (CR)

Итак, это законная последовательность UTF-8.

Однако стандартные функции Prelude изначально просто сделали ASCII. Я не знаю, что они делают сейчас, но посмотрите на этот вопрос Как GHC/Haskell решает, какую кодировку символов он собирается декодировать/кодировать из/в? еще несколько идеи. А затем используйте http://hackage.haskell.org/package/utf8-string вместо функций Prelude.