椿の日記

たぶんプログラムの話をします

Haskell@Windowsのコンソールで日本語が文字化けする話の対策

コンソールのコードページがCP932なので、最終的にCP932に変換しなければならないのですが、どうせWindowsでしか起こらない問題なので、WindowsのAPIを使っちゃいます。

import Data.Word
import Foreign.Ptr
import Foreign.C.Types
import Foreign.C.String
import Foreign.Marshal.Alloc
import System.IO.Unsafe

foreign import stdcall "WideCharToMultiByte" c_WideCharToMultiByte ::
    Int ->              -- CodePage
    Word32 ->           -- dwFlags
    Ptr CWchar ->       -- lpWideCharStr
    Int ->              -- cchWideChar
    Ptr CChar ->        -- lpMultiByteStr
    Int ->              -- cchMultiByte
    Ptr CChar ->        -- lpDefaultChar
    Ptr Bool ->         -- lpUsedDefaultChar
    IO Int

toCP932 :: String -> String
toCP932 cs = unsafePerformIO $ do
    withCWStringLen cs (\(src,srcLen) -> do
        dstLen <- c_WideCharToMultiByte 0 0 src srcLen nullPtr 0 nullPtr nullPtr
        allocaBytes dstLen (\dst -> do
            c_WideCharToMultiByte 0 0 src srcLen dst dstLen nullPtr nullPtr
            peekCStringLen (dst,dstLen)))

main = putStrLn $ toCP932 "ほげ"