[Oracle] UTL_FILE でキャラクタ・セットを変換して読み書きする(2) | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

UTL_FILE パッケージを使用してテキストファイルの入出力を行う際、CONVERT 関数を使用するとデータベースのキャラクタ・セット以外のキャラクタ・セットのテキストファイルの入出力を行うことができます。

Oracle10g ではこの方法に加えて、UTL_FILE パッケージの新機能と、UTL_I18N という新パッケージを組み合わせて使用する方法も考えられます。


Oracle10g から 多言語アプリケーション開発用に UTL_I18N というパッケージが追加されています。このパッケージに含まれる STRING_TO_RAW、RAW_TO_CHAR、RAW_TO_NCHAR といったファンクションを使うと VARCHAR2、NVARCHAR2 文字列と Oracle で使用できる任意のキャラクタ・セットのバイナリデータの変換が可能になります。

さらに、Oracle10g では UTL_FILE パッケージの FOPEN ファンクションの open_mode に'wb'(バイトの書き込み)、'rb'(バイトの読み込み)、'ab'(バイトの追加)が追加されています。

これらのモードでファイルをオープンすると、GET_RAW、PUT_RAW をコールしてバイナリデータの読み書きができるようになります。


つまり、これらの機能を組み合わせると、文字列データを任意のキャラクタ・セットのバイナリデータ変換して入出力することが可能になるというわけです。


キャラクタ・セットを変換してファイルに書き込む
VARCHAR2 文字列を EUC のバイナリデータに変換してファイルに書き込む場合は以下のように記述します。

DECLARE
  wk_file    UTL_FILE.FILE_TYPE;
  wk_buffer  VARCHAR2(32767);
BEGIN
  wk_file := UTL_FILE.FOPEN( 'C:\TEMP','test.txt', 'wb', 32767 );
  wk_buffer := 'キャラクタ・セット変換出力のテストです。' || CHR(10);
  UTL_FILE.PUT_RAW( wk_file, UTL_I18N.STRING_TO_RAW( wk_buffer, 'JA16EUC' ), TRUE );
  UTL_FILE.FCLOSE( wk_file );
END;
/


キャラクタ・セットを変換してファイルから読み込む
ファイルから読み込んだ EUC のバイナリデータを データベース・キャラクタ・セット(ここでは SJIS) の文字列に変換する場合は以下のように記述します。


DECLARE
  wk_file        UTL_FILE.FILE_TYPE;
  wk_raw_buffer  RAW(32767);
  wk_buffer      VARCHAR2(32767);
BEGIN
  wk_file := UTL_FILE.FOPEN( 'C:\TEMP','test.txt', 'rb', 32767 );
  UTL_FILE.GET_RAW( wk_file, wk_raw_buffer );
  wk_buffer := UTL_I18N.RAW_TO_CHAR( wk_raw_buffer, 'JA16EUC' );
  DBMS_OUTPUT.PUT_LINE( wk_buffer );
  UTL_FILE.FCLOSE( wk_file );
END;
/


ただし、この方法では文字列データをバイナリデータとして入出力しますので、改行コードをケアしなければなりません。

例えば、上記の書き込みの例では改行コードとして LF(0x0A)を付与していますが、環境によってはこれを CRLF(0x0D 0x0A)にしたり、CR(0x0D)にしたりする必要があります。

また上記の読み込みの例も、本来は一定バイト数ごとに区切って読み込み、バイナリデータに含まれる改行コードごとにデータを分解するなどの処理が必要になります。

文字列データとして入出力する場合と比べるとこの辺りが面倒なところです。


しかし、逆に文字列データとして入出力する場合、改行コードをケアする必要はありませんが、既定の改行コード以外の改行コードのテキストファイルの入出力時に問題が発生することがあります。

バイナリデータとして入出力する上記の方法は、こういったケースで有効な手段となりえるでしょう。




【関連エントリ】
[Oracle] テキストファイルの入出力方法 2004/07/14
[Oracle] Linux環境でのUTL_FILEの不思議な挙動 2007/01/16
[Oracle] UTL_FILE.PUT_LINE で書き出される改行コードがおかしい! 2007/01/17
[Oracle] UTL_FILE.GET_LINE で改行コードの一部が読み込まれる! 2007/01/18
[Oracle] UTL_FILE でキャラクタ・セットを変換して読み書きする(1) 2007/02/21
[Oracle] UTL_FILE でキャラクタ・セットを変換して読み書きする(2) 2007/02/27