記事
· 2025年7月3日 4m read

文字コードが不明なファイルや文字列を正しく処理する方法

これは InterSystems FAQ サイトの記事です。

InterSystems 製品では、ファイルオープン時に文字コードを指定すれば指定の文字コードで正しくファイルの中身を処理できます。

文字コードを指定しない場合、InterSystems 製品をインストールした OS に合わせて設定されたファイル I/O 用文字コードを利用してファイルをオープンします(Linux 系は UTF8、Windows は SJIS)。

また、文字列については文字コードが判明していれば $ZCONVERT() 関数を使用して指定文字コードで文字列を処理することができます。

 例)$ZCONVERT(文字列,"I","IRIS内文字コード")

文字コードが不明な場合、残念ながら InterSystems 製品だけでそのコードを判別することができないため、例えば Embedded Python で Python の chardet パッケージを使用して文字コード判別し、IRIS 内文字コードを取得しファイルオープン、文字列の文字コード変換をすることができます。

chardetパッケージについては、外部サイトですが参考となります。ぜひご参照ください。

参考ページ:[解決!Python]テキストファイルのエンコーディングを調べて、その内容を読み込むには(chardetパッケージ)

以下、具体的な処理内容です。文字コードが不明なファイルに対する処理例として記載しています(文字列に対する処理例は末尾にあります)。

IRIS のクラス定義に以下のように language=python を設定したクラスメソッドを用意します。

/// ファイルのエンコードを確認して返す
/// 第1引数:ファイル名(フルパス)
/// 戻り値:エンコード
/// 事前準備:Pythonのchardetパッケージをインストールしておく必要があります
/// 参考URL:https://atmarkit.itmedia.co.jp/ait/articles/2105/11/news015.html
ClassMethod GetEncode(filename As %String) As %String [ Language = python ]
{
import iris
from chardet import detect  # chardetパッケージからdetect関数をインポート
with open(filename, 'rb') as f:  # バイナリファイルとして読み込みオープン
    b = f.read()  # ファイルから全データを読み込み
    enc = detect(b)  # 読み込んだデータdetect関数に渡して判定する
#print(enc)
return enc["encoding"]
}

 

ターミナルで単体テストを行った結果は以下の通りです。

例:ECU-JPで保存されているファイルを確認した場合

この後、IRIS 内ユーティリティメソッドを利用して IRIS 用文字コードを入手しファイルオープン時の文字コードに指定します。

set TranslateTable=##class(%Net.Charset).GetTranslateTable(ここにPythonで確認したエンコード)

 

コード詳細は以下の通りです。

ClassMethod test(filename As %String)
{
    if $Get(filename)="" {
        write "第1引数にファイル名をフルパスで指定してください",!
        return
    }
    // Pythonのchardetパッケージを利用したエンコード調査を実行します
    set encode=..GetEncode(filename)
    if $get(encode)="" {
        write filename," のエンコードが入手できませんでした",!
        return
    }
    // エンコードが返った来た場合、IRIS内の文字コードを調査
    set TranslateTable=##class(%Net.Charset).GetTranslateTable(encode)
    
    write "IRISの文字コードは:",TranslateTable,!
    write "ファイルの中身は以下==",!
    set fs=##class(%Stream.FileCharacter).%New()
    set fs.TranslateTable=TranslateTable
    do fs.LinkToFile(filename)
    while fs.AtEnd=0 {
        write fs.ReadLine(),!
    }
    kill fs
}

 

実行例は以下の通りです。

USER>do ##class(FAQ.Utils).test("/data/sample1.txt")
IRISの文字コードは:EUC
ファイルの中身は以下==
あいうえお
かきくけこ
さしすせそ

USER>

 

ファイルではなく文字列に対して操作する場合は、以下の手順で実行します。

1、Python の chardetパッケージを利用してエンコードを入手

set encode=##class(FAQ.Utils).GetEncode("/data/sample1.txt")

 

2、IRIS 用文字コードを入手

USER>set TranslateTable=##class(%Net.Charset).GetTranslateTable(encode)

USER>write TranslateTable
EUC
USER>

 

3、$ZCONVERT()関数を使用してコードを変換

USER>write $ZCONVERT(reco,"I",TranslateTable) // recoに対象文字列が含まれているとします
あいうえお
USER>
ディスカッション (0)1
続けるにはログインするか新規登録を行ってください