2012-10-15 18 views
10
readFile "file.html" 
"start of the file... *** Exception: file.html: hGetContents: invalid argument (invalid code page byte sequence) 

これはnotepad ++で作成されたUTF-8ファイルです...どのようにしてhaskellでファイルを読むことができますか?haskell - 無効なコードページのバイトシーケンス

+0

おそらく、このエラーを示す最小限のファイルの16進ダンプを投稿できますか?私はあなたのエラーを複製することはできません。 – ghoti

+1

この文字を使用してください: 'č' –

+0

あなたのロケールは何ですか?それはutf-8のものか何かucs2ish(notepad ++はWindowsを示唆していますか?)ですか? –

答えて

12

デフォルトでは、ファイルはシステムロケールで読み込まれるため、非標準のエンコーディングを使用するファイルがある場合は、ファイルハンドルのエンコーディングを自分で設定する必要があります。

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

をご利用ください。これは何のエラー処理が含まれていない、より良い方法は、このようにthis siteによる

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 
+0

私は(' foo'のように、 '_bom'について知りませんでしたが)同様のものを考え出しました。 'readFile'で行うように、計算を外部に行うことは可能ですか? 'foo'の例は' hClose'の行を使わないとうまくいきます(そして私のおもちゃのプログラムではOKですが、 "正しい方法"を知りたいのですが) 'IO(String、ハンドル) '?) –

+0

あなたのファイルを遅延読み込みする必要がある場合は、少し難しいです。 'hClose'は計算が戻るときにファイルを閉じます。これはファイルの何かが読み込まれる前に起こるかもしれません。したがって、ファイル全体を一度にメモリに保存することができれば、単純な '' length contents '' seq' return contents''を実行すると、ファイル全体が読み込まれ、処理が外にできます。それ以外の場合は、ファイルを怠惰な 'ByteString'として読み込み、それを' utf8-string'パッケージの 'Data.ByteString.Lazy.UTF8.toString'を使って変換するのが最善でしょう。 –

+0

'ByteString'が物事をより簡単にしてくれます(私は初心者ですが)。' readFile'はレイジーですよね?では、ファイルをどのように閉じるのですか?最後の文字が読み込まれたことをチェックしますか?私はそれを何とか模倣することができますか? –

1

になり、次のように、あなたの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) 

だから、そのA法的なUTF-8シーケンス。

しかし、標準のPrelude関数はもともとASCIIを行っただけです。私は彼らが今何をしているのか分からないが、いくつかのアイデアについてはこの質問How does GHC/Haskell decide what character encoding it's going to decode/encode from/to?を参照してください。そして、Prelude関数の代わりにhttp://hackage.haskell.org/package/utf8-stringを使用してください。

関連する問題