2013.03.26

Haskell使ってWindows上でJISで書かれたファイルをSJIS(CP932)に変換して表示してみた

コードこんな感じ。

{-# LANGUAGE ImplicitParams #-}

import Prelude hiding (getContents,putStrLn,readFile)
import System.IO.Encoding
import Codec.Text.IConv
import Data.Encoding
import Data.Encoding.ISO2022JP
import Data.Encoding.CP932

main = do
    let ?enc = ISO2022JP
    s <- System.IO.Encoding.readFile "test.txt"
    let bs = Data.Encoding.encodeLazyByteString ISO2022JP s
    let sbs = Codec.Text.IConv.convert "ISO-2022-JP" "CP932" bs
    let ss = Data.Encoding.decodeLazyByteString CP932 sbs
    let ?enc = CP932
    System.IO.Encoding.putStrLn ss
    return ()

System.IO.EncodingのreadFile使ってISO2022JPで文字コードを指定して読み込み。
読み込んだ文字列をencodeLazyByteString使って文字コード指定してByteStringに変換。
convert使ってISO-2022-JPからCP932に変換。
convertの結果のByteStringをCP932の文字コードを指定してdecodeLazyByteStringでStringに変換。
最後にCP932の文字コードを指定してputStrLnで画面出力でCP932で出力できたよ。

Data.Encoding.CP932はまだ対応してなかったので実装した。
ついでにData.Encoding.SJISもコード表作ってみた。
そのうち本家に取り込むかpatch載せるかしよう。

======
2013/5/28 追記

これを本家に突っ込むほどのモチベーションが沸かなかったので
とりあえずpatchの直リン貼り。
encoding-0.6.7.2へのpatchファイルになってます。
https://raw.github.com/endhrk/encoding/master/encoding.diff

======
2016/8/23 追記

このパッケージをまた使うことになりいよいよ面倒なので本家にパッチを送信。
encoding-0.8.1で取り込まれました。
https://hackage.haskell.org/package/encoding

2013.03.25

HaskellのSystem.IO.EncodingをWindowsにインストールしようとしてハマった

色々遠回りしてるので、先に結論書いときます。

$ cabal install encoding -f-systemEncoding

これで行けます。

環境はこんな感じ

  • mingw32
  • ghc 7.4.2
  • cabal 1.14
  • encoding 0.6.7.2

以下試行錯誤の経過。

普通にcabalでインストールしようとしてみると怒られた。

$ cabal install encoding

<中略>
Configuring encoding-0.6.7.2…
setup.exe: Missing dependency on a foreign library:
* Missing (or bad) header file: system_encoding.h
This problem can usually be solved by installing the system package that
provides this library (you may need the “-dev” version). If the library is
already installed but in a non-standard location then you can use the flags
–extra-include-dirs= and –extra-lib-dirs= to specify where it is.
If the header file does exist, it may contain errors that are caught by the C
compiler at the preprocessing stage. In this case you can re-run configure
with the verbosity flag -v3 to see the error messages.
cabal.exe: Error: some packages failed to install:
encoding-0.6.7.2 failed during the configure step. The exception was:
ExitFailure 1

よくわからないので “-v3” を付けて再実行。

$ cabal install encoding -v3

<中略>
ExitFailure 1 with error message:
In file included from C:\DOCUME~1\hoge\LOCALS~1\Temp\1\23868.c:1:0:
./system_encoding.h:4:22: fatal error: langinfo.h: No such file or directory
compilation terminated.
setup.exe: Missing dependency on a foreign library:
* Missing (or bad) header file: system_encoding.h
This problem can usually be solved by installing the system package that
provides this library (you may need the “-dev” version). If the library is
already installed but in a non-standard location then you can use the flags
–extra-include-dirs= and –extra-lib-dirs= to specify where it is.
If the header file does exist, it may contain errors that are caught by the C
compiler at the preprocessing stage. In this case you can re-run configure
with the verbosity flag -v3 to see the error messages.
World file is already up to date.
cabal.exe: Error: some packages failed to install:
encoding-0.6.7.2 failed during the configure step. The exception was:
ExitFailure 1

langinfo.h が見つからないらしい。

GnuWinのLibGW32Cに入ってたのでこいつをインストール。
http://gnuwin32.sourceforge.net/packages/libgw32c.htm
※インストーラ付きはこっち -> http://gnuwin32.sourceforge.net/downlinks/libgw32c.php

headerファイルの場所を指定して再度インストール。

$ cabal install encoding –extra-include-dirs=”C:\Program Files\GnuWin32\include\glibc”

<中略>
Data\Encoding.hs:0:4: lexical error (UTF-8 decoding error)
cabal.exe: Error: some packages failed to install:
encoding-0.6.7.2 failed during the building phase. The exception was:
ExitFailure 1

文字コードがなんか駄目らしい。

応急処置。

$ export LANG=C

もいっかい実行。

$ cabal install encoding –extra-include-dirs=”C:\Program Files\GnuWin32\include\glibc”

<中略>
Registering encoding-0.6.7.2…
Installing library in C:\Documents and Settings\hoge\Application
Data\cabal\encoding-0.6.7.2\ghc-7.4.2
Registering encoding-0.6.7.2…

やっと通った。

しかしSystem.IO.Encodingを使うプログラムコンパイル時にリンクエラー。

$ ghc test.hs
[1 of 1] Compiling Main ( test.hs, test.o )
Linking test.exe …
C:\Documents and Settings\hoge\Application Data\cabal\encoding-0.6.7.2\ghc-7.
4.2/libHSencoding-0.6.7.2.a(system_encoding.o):system_encoding.c:(.text+0x22): u
ndefined reference to `nl_langinfo’
collect2: ld returned 1 exit status

あらためて色々確認。
http://hackage.haskell.org/packages/archive/encoding/0.6.7.2/doc/html/System-IO-Encoding.html
System.IO.Encodingのドキュメントを見ると…

Returns the encoding used on the current system. Currently only supported on Linux-alikes.

Linuxだけしかサポートしてないよ!

CHANGELOGファイルを見ると…
http://code.haskell.org/encoding/CHANGELOG

add -systemEncoding flag for Windows builds

Windows用にsystemEncodingを無効にするフラグが付いている!

ちゃんとドキュメント見てない僕が悪かったんや…

ということでWindowsでSystem.IO.Encodingを使いたい時は

$ cabal install encoding -f-systemEncoding

でした。

遠回りしすぎた…