Julia Advent Calendar 2020,16日目です.
Julia で,漢字コード変換を行うパッケージ NKFtool
を紹介します.
Julia は Unicode が大好き
Julia は Unicode が大好きです.変数名,関数名,演算子を,Unicode文字で表せます.(以前紹介記事を書きました → UTF-8 表記の演算子たち).
Julia の文字・文字列は、UTF-8 符号です. 可変長の UTF-8 を,Julia はしなやかに扱います.
例えば,eachindex(s)
は,文字列 s
に入っている各文字の添字(何バイト目か)を順番に取り出すイテレータです. 以下の例では,絵文字が 4 バイト,漢字が 3 バイト,半角文字は 1 バイトで表されていることが分かります.(絵文字 🍣 をJuliaの REPLで入力するには \:sushi:
と入力してからTABキーで変換します).
julia> collect(eachindex("s🍣寿ss"))
5-element Array{Int64,1}:
1
2
6
9
10
漢字コードの話
Unicode が使われる以前から,複数の漢字コードが存在しています.
主な漢字コードは,JISコード,日本語EUC (Extended Unix Code),Shift_JIS の三つです. 日頃 Windows 上で Microsoft Office を使う人は, Shift_JIS 文字(の拡張)を使っているはずです. 各種測定器が吐き出すファイルも Shift_JIS で書かれるものが多いです.
さて,UTF-8 以外で符号化されたファイルをJuliaで扱うには,事前に UTF-8 に変換したファイルを用意しておけばよいのですが、手間ですし,ファイルが増えてしまいます. 今回紹介する NKFtool
を使えば、必要なときに Julia プログラム中からコード変換して読めるので、この悩みを解消できます.
nkf の紹介
nkf (Network Kanji Filter)は,漢字コード変換のためのコマンドライン・ツールです.
多くのパッケージマネージャから nkf
をインストールできます.例えば,Mac の Homebrew からインストールするには
% brew install nkf
% nkf --version
Network Kanji Filter Version 2.1.5 (2018-12-15)
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).
Copyright (C) 1996-2018, The nkf Project.
(nkf
は, Unicode や the Internet が広く普及する前から存在する由緒あるツールです)
文字コード変換の標準的なツールである iconv
と比較して nkf
は,以下の点で便利です.
- 入力コードを自動で推定するので,指定しなくてよい(ただし、推定が失敗する場合もある)
- 改行記号を変換できる (CR, LF, CR+LF)
- 独自拡張された漢字コード(の一部)も取り扱うことができる
NKFtool の導入と起動
NKFtool
パッケージは,Julia 内から nkf
を呼ぶためのパッケージです.Juliaのパッケージマネージャからインストールできます.nkf
は予め入れておいてください.
julia> # ] キーを押してパッケージモードに入る
pkg> add NKFtool
julia> # CTRL + C で REPL に戻る
NKFtool.nkf_version()
は,nkf --version
の出力を文字列として返します.
julia> nkf_version() |> println
Network Kanji Filter Version 2.1.5 (2018-12-15)
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).
Copyright (C) 1996-2018, The nkf Project.
NKFtool.nkf_help()
は,nkf --help
の出力を文字列として返します. nkf
のオプション確認に便利です.
julia> nkf_help() |> println
Usage: nkf -[flags] [--] [in file] .. [out file for -O flag]
j/s/e/w Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP
UTF options is -w[8[0],{16,32}[{B,L}[0]]]
J/S/E/W Specify input encoding ISO-2022-JP, Shift_JIS, EUC-JP
UTF option is -W[8,[16,32][B,L]]
# 以下省略
漢字コードを推定する
NKFtool.nkf_guess(s)
は,漢字コードを推定するコマンド nkf -g
の出力を文字列として返します. 入力 s
には,文字列またはストリームを指定します.
julia> nkf_guess("おはよう")
"UTF-8"
julia> nkf_guess(IOBuffer(raw"おはよう"))
"UTF-8"
漢字コードを変換する
NKFtool.nkf_convert(s, options)
は,options
に従い漢字コードを変換した文字列を返します. 入力 s
には,文字列またはストリームを指定します. options
は nkf
コマンドにそのまま渡されます (nkf --help
で表示されるオプションの全てを指定できるわけではありません. 特に、入力ファイルを指定してしまうと、そこから文字列を読み込んでしまうでしょう).
出力漢字コードを指定する主なオプションは,以下の通りです.(小文字で指定します)
-
-j
: JIS漢字コード, -
-e
: 日本語EUCコード, -
-s
: SHIFT_JIS コード -
-w
または-w0
: UTF-8
options
は省略可能です。既定値は -w -m0
(出力コード UTF-8, no MIME encoding) です.
文字列を,色々な漢字コードに変換してみます. nkf_guess()
を用いて,漢字コードが正しく推定されることを確かめましょう.
julia> nkf_convert( raw"おはよう", "-j") |> nkf_guess
"ISO-2022-JP"
julia> nkf_convert( raw"おはよう", "-e") |> nkf_guess
"EUC-JP"
julia> nkf_convert( raw"おはよう", "-s") |> nkf_guess
"Shift_JIS"
julia> nkf_convert( raw"おはよう", "-w") |> nkf_guess
"UTF-8"
julia> nkf_convert( raw"おはよう") |> nkf_guess
"UTF-8"
漢字コードを変えてファイルに書き込む
漢字コードを変えてファイルに書き込むには,nkf_convert(s, options)
の結果を,出力ストリームに渡せばよいでしょう.
以下の例では Shift_JIS コードのファイルを作りました.
julia> open("morning_sjis.txt","w") do f
print(f, nkf_convert(raw"おはよう\n", "-s"))
print(f, nkf_convert(raw"おはよう\n", "-s"))
end
julia> open("morning_sjis.txt") do f
nkf_guess(f)
end
"Shift_JIS"
julia> # 最初の1行で,コードを判定する
readline("morning_sjis.txt") |> nkf_guess
"Shift_JIS"
ファイルから読み込む
色々な漢字コードで書かれたファイルから読み込むには,入力ファイルのストリーム f
を nkf_convert(f, options)
に渡せばよいでしょう.
Julia文字列 として読み込む場合には options
を省略してもよいです. (options
の既定が -w -m0
だから)
julia> morning_utf=open("morning_sjis.txt") do f
nkf_convert(f)
end
"おはよう\\nおはよう\\n"
入力コードは誤判定がありうるので,事前に分かっているなら指定するとよいでしょう.
入力コードを指定する主なオプションは,以下の通りです.(各々の出力コード指定を大文字にした文字です)
-
-J
: JIS漢字コード -
-E
: 日本語EUCコード -
-S
: SHIFT_JIS コード
julia> morning_utf=open("morning_sjis.txt") do f
nkf_convert(f, "-S" ) # Shift_JIS コードを読む
end
"おはよう\\nおはよう\\n"
Windows(の一部?)は,独自拡張した Shift_JIS コードを使用します(こちらの記事などを参照 → 本当は怖くないCP932 や nkfでCP932←→UTF-8の変換をする ). 例えば,CP932コードで書かれたテキスト・ファイルを読み込むなら --cp932
オプションを指定しましょう (--cp932
は, nkf --help
には表示されない隠しオプションです).
julia> open("morning_cp932.txt","w") do f
print(f, nkf_convert(raw"おはよう~\n", "--oc=cp932")) # CP932 へ変換
end
julia> open("morning_cp932.txt") do f
nkf_guess(f)
end
# Shift_JIS として判定される
"Shift_JIS"
julia> open("morning_cp932.txt") do f
nkf_convert(f, "--cp932" )
end
"おはよう~\\n"
Shift_JIS で書かれた CSV ファイルを読んで DataFrame を作る
応用として, Shift_JIS で書かれた CSV ファイルから, DataFrame を作ってみましょう。
私の用いているデータロガーは,次のような CSV ファイルを吐き出します.
(Shift_JIS で表されています)
"ファイル名","AUTO0001.CSV","V 1.11"
"タイトルコメント",""
"トリガ時刻","20-03-25 10:45:00"
"CH","Mode","Range","Comment","Scaling","Ratio","Offset"
"CH-1","電圧","100V","","OFF","-","-"
"CH-2","電圧","100V","","OFF","-","-"
"CH-3","熱電対","2000℃","","OFF","-","-"
"CH-4","熱電対","2000℃","","OFF","-","-"
"Time","CH-1[V]","CH-2[V]","CH-3[℃]","CH-4[℃]","Event",
0.000000000E+00, 1.00000E-02, 1.50000E-02, 1.96000E+01, 1.94000E+01, 0,
1.000000000E+01, 1.50000E-02, 1.00000E-02, 1.96000E+01, 1.93000E+01, 0,
以下省略
これから DataFrame
を作るには、以下の手順を踏みます.
まず NKFtool_convert()
で UTF-8文字列に変換します. これを IOBuffer()
に入れるとよいでしょう. データのヘッダ行は "Time" で始まる行として求められます. CSV.read(..., DataFrame)
を呼ぶと DataFrame
に変換できます.
using NKFtool
using CSV, DataFrames
# ヘッダー行を求める
function get_headerlineno(input_io)
header_lineno=0
lineno=0
while true
text=readline(input_io)
isempty(text) && break
lineno += 1
# @show lineno, text
if startswith(text,"\"Time\"")
header_lineno=lineno
break
end
end
header_lineno
end
# CSV を読んで DataFrames を作る
function read_CSV(inout_csv_path)
input_csv_texts = open(inout_csv_path) do f
nkf_convert(f)
end
header_lineno=get_headerlineno(IOBuffer(input_csv_texts))
CSV.read(IOBuffer(input_csv_texts), header=header_lineno, DataFrame)
end
実行してみましょう. 期待したとおりに DataFrame を作成できました (MacOSXターミナル上で起動した Julia REPLでは [℃]
が [@@]
に化けてしまいましたが、Visual Studio Code 内の Terminal で起動した Julia REPL では化けずに表示できました).
julia> read_CSV("~/AUTO0001.CSV")
4×7 DataFrame
Row │ Time CH-1[V] CH-2[V] CH-3[℃] CH-4[℃] Event Column7
│ Float64 Float64 Float64 Float64 Float64 Int64 Missing
─────┼───────────────────────────────────────────────────────────────
1 │ 0.0 0.01 0.015 19.6 19.4 0 missing
2 │ 10.0 0.015 0.01 19.6 19.3 0 missing
3 │ 20.0 0.015 0.01 19.5 19.4 0 missing
4 │ 30.0 0.02 0.01 19.5 19.4 0 missing
以下省略
終わりに
以上、Juliaプログラム中で、漢字コードを変換できる NKFtool
を紹介しました. CSV
を経由して DataFrame
を作れば、データ操作が早く楽になるはずです. どんどん活用しましょう.
また、同パッケージのソースは、Julia内でコマンドライン・ツールを呼ぶ例として参考になります。 別のツールを呼び出すパッケージを作る際に眺めてみるとよいでしょう。