ユニコード表をテキストファイルとして保存


2012年 12月 14日

さて、ファイルへの出力が分かったので、何か役立ちそうなテキストファイルを出力してみよう。
ということで、Unicode表を作ってみよう。
ユニコード漢字全文字を作るのは、ユニコード全20902字で説明したが、プログラムを再掲しよう。

import Data.Char
import Data.List

fromK :: Char -> [Char]
fromK c = c :  fromK (chr ((ord c) + 1))
unicode = take 20902 (fromK '一')

こでで、unicode を評価すれば、長さが20902の文字列ができあがる。
これをそのままファイルとして出力するには、

*Main Data.List> writeFile "unicodetest.txt" unicode

だけで良いのだが、これでは、1行に20902文字並んだとんでもないファイルができるだけだ。
一定の間隔で改行を入れないと表示のときにこまるので、一定間隔でこの長い文字列(リスト)を切ろう。
リストを2つに分ける関数 splitAtがある。切る位置と、元のリストを与えれば、2つに分けてくれる。

*Main Data.List> :t splitAt
splitAt :: Int -> [a] -> ([a], [a])

さて、これを使って、一定間隔でリストを切る関数を作ってみた。

splitEvery     :: Int -> [a] -> [[a]]
splitEvery n s
           | null sx    = [fx]
           | otherwise  = fx : (splitEvery n sx)
          where (fx,sx) = splitAt n s

動作確認すると、こんな感じ。

*Main Data.List> splitEvery 5 [1..16]
[[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16]]

これで、長大な文字列を32文字毎に切った文字列のリストができる。

unicode = splitEvery 32 (take 20902 (fromK '一'))

次に、各32文字長の文字列を改行を挟みながら1つの文字列にしてしまおう。
改行で区切る関数がlinesなのだが、その逆の改行を挟みながらくっつける関数はunlineである。

unicodetable = unlines unicode

これで、32文字毎に改行したものが得られた。

*Main Data.List> putStrLn (take 100 unicodetable)
一丁丂七丄丅?万丈三上下丌不与?丐丑丒?且丕世丗丘丙????丞丟
?両?丣两?並?丨?个丫?中丮丯丰丱串??丵丶?丸丹?主丼??丿
乀乁乂乃乄久?乇???之?乍乎乏?乑???乕乖乗乘乙乚?乜九乞也
?
*Main Data.List>

これをファイルに書き出せば、ユニコード表の完成である。

しかし、これでは、コードの対応を取り難い。
各行の最初に、文字コードを入れてみよう。

unicodetable = unlines (map addhead unicode)

addhead xa@(x:_) = show (ord x) ++ "  " ++ xa

文字列の先頭に、先頭文字のコードを入れてみた。
これで、もう一度プログラムを読み込んで実行していみよう。

*Main Data.List> putStrLn (take 100 unicodetable)

*Main Data.List> putStrLn (take 100 unicodetable)
19968  一丁丂七丄丅?万丈三上下丌不与?丐丑丒?且丕世丗丘丙????丞丟
20000  ?両?丣两?並?丨?个丫?中丮丯丰丱串??丵丶?丸丹?主丼??丿
20032  乀乁乂乃乄久?乇???之?

先頭の文字コードが10進数のままだと分かりにくい。
ここは16進数に直してみよう。

だが、長くなったので、つづく。