Camomile 使い方メモ (2) [OCaml]
Camomile についてさらに調べる。
Camomile のユニコード文字列型には何種類かあるけれども文字型は UChar という1つしかない。
特定のエンコーディングで書かれたテキストファイルから読み込むには以下のようにする。hyoji.txt は Shift_JIS で「表示」の2文字だけが書かれたファイルとする。
# let inc = open_in "hyoji.txt";; val inc : in_channel = <abstr> # let sjis = CamomileLibrary.Default.Camomile.CharEncoding.of_name "SHIFT_JIS";; val sjis : CamomileLibrary.Default.Camomile.CharEncoding.t = <abstr> # let inc' = new CamomileLibrary.Default.Camomile.CharEncoding.in_channel sjis inc;; val inc' : CamomileLibrary.Default.Camomile.CharEncoding.in_channel = <obj> # let hyo = inc'#get ();; val hyo : CamomileLibrary.UChar.t = <abstr> # let ji = inc'#get ();; val ji : CamomileLibrary.UChar.t = <abstr> # inc'#get ();; Exception: End_of_file.
new CharEncoding.in_channel で得られるオブジェクトは普通の入力チャネルを UChar 型単位のチャネルに変換したもの。このオブジェクトから get メソッドで1文字ずつ取得することができる。UChar 型として2文字を読んだところで EOF になっているのが分かる。
このオブジェクトは OOChannel.stream_of_channel 関数を使って Stream.t 型にすることもできる。馴染み深い分こちらのインターフェイスのほうが使いやすいこともあるだろう。
# CamomileLibrary.Default.Camomile.OOChannel.stream_of_channel inc';; - : CamomileLibrary.UChar.t Stream.t = <abstr>
ところで UChar.code 関数を使うと UChar 型の値をユニコードのコードを示す整数に変換できる。
先に取得した「表示」の2文字がそれぞれユニコードで U+8868 と U+793A であることを確かめてみよう。
# Printf.sprintf "%x" (CamomileLibrary.Default.Camomile.UChar.code hyo);; - : string = "8868" # Printf.sprintf "%x" (CamomileLibrary.Default.Camomile.UChar.code ji);; - : string = "793a"
UChar のチャネルなりストリームなりから得た文字を UTF8 や UText などの文字列にするにはどうしたらよいか。一つは UChar のチャネルを変換してユニコード文字列の行から成るチャネルにする方法がある。
# module L = CamomileLibrary.Default.Camomile.ULine.Make(CamomileLibrary.UTF8);; module L : sig type text = CamomileLibrary.UTF8.t class input_line : CamomileLibrary.UChar.t #CamomileLibrary.OOChannel.obj_input_channel -> [text] CamomileLibrary.OOChannel.obj_input_channel class output_line : ?sp:CamomileLibrary.Default.Camomile.ULine.separator -> CamomileLibrary.UChar.t #CamomileLibrary.OOChannel.obj_output_channel -> [text] CamomileLibrary.OOChannel.obj_output_channel end # let l = new L.input_line inc';; val l : L.input_line = <obj> # let line = l#get ();; val line : L.text = "\232\161\168\231\164\186" # CamomileLibrary.UTF8.length line;; - : int = 2 # let line = l#get ();; Exception: End_of_file.
ULine はファンクタで、使いたいユニコード文字列型に適用して具体的なモジュールを得る。
得られたモジュールの input クラスを使うと UChar のチャネルをユニコード文字列の行単位のチャネルに変換できる。
もう一つはユニコード文字列型には Buf サブモジュールで文字列バッファが提供されているのでそれをつかってもよいかもしれない。
# let buf = CamomileLibrary.UTF8.Buf.create 256;; val buf : CamomileLibrary.UTF8.Buf.buf = <abstr> # while true do CamomileLibrary.UTF8.Buf.add_char buf (inc'#get ()) done;; Exception: End_of_file. # let s = CamomileLibrary.UTF8.Buf.contents buf;; val s : CamomileLibrary.UTF8.t = "\232\161\168\231\164\186" # CamomileLibrary.UTF8.length s;; - : int = 2
ここまで分かればもう大抵のやりたいことはできそうかなあ。出力側はまあ似たような感じだろう。
コメント 0