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

Archive Redo Blog

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

UTL_FILE パッケージを使ってテキストファイルの入出力を行う場合、読み書き可能なキャラクタ・セットはデータベースのキャラクタ・セットに依存します。

FOPEN、GET_LINE、PUT、PUT_LINE などを使用した場合はデータベース・キャラクタ・セットに、FOPEN_NCHAR、GET_LINE_NCHAR、PUT_NCHAR、PUT_LINE_NCHAR などを使用した場合は各国語キャラクタ・セットに依存します。

つまり、データベース・キャラクタ・セットが'JA16SJIS'の場合、 FOPEN、GET_LINE、PUT、PUT_LINE を使用して読み書き可能なキャラクタ・セットは JA16SJIS となり、各国語キャラクタ・セットが'AL32UTF8'の場合、FOPEN_NCHAR、GET_LINE_NCHAR、PUT_NCHAR、PUT_LINE_NCHAR を使用して読み書き可能なキャラクタ・セットは AL32UTF8UTF8 となります。

しかし、CONVERT 関数を使えば、データベースのキャラクタ・セット以外のキャラクタ・セットのテキストファイルの入出力を行うことも可能です。


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

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

※なぜか wk_buffer のデータ型は VARCHAR2 にしないと正常に変換されないようです。

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

DECLARE
  wk_file    UTL_FILE.FILE_TYPE;
  wk_buffer  VARCHAR2(32767);
BEGIN
  wk_file := UTL_FILE.FOPEN( 'C:\TEMP','test.txt', 'r', 32767 );
  UTL_FILE.GET_LINE( wk_file, wk_buffer );
  wk_buffer := CONVERT( wk_buffer, 'JA16SJIS','JA16EUC' );
  DBMS_OUTPUT.PUT_LINE( wk_buffer );
  UTL_FILE.FCLOSE( wk_file );
END;
/

※なぜか wk_buffer のデータ型は VARCHAR2 にしないと正常に変換されないようです。

ファイル名のキャラクタ・セットがデータベースのキャラクタ・セットと一致しないファイルをオープンする
UTL_FILE.FOPEN で指定するファイル名を CONVERT 関数で変換します。

wk_file := UTL_FILE.FOPEN( 'C:\TEMP',CONVERT('テスト.txt', 'JA16EUC' ), 'w', 32767 );


これらの方法は OS の文字コードとデータベースのキャラクタ・セットが一致しない環境において、Oracle から OS の文字コードに合わせたテキストファイルの入出力を行う1つの手段です。

ただし、各キャラクタ・セットは完全互換ではないため、変換できない文字が存在する可能性があります。上記の方法でも変換できない文字があった場合は'?'などに置換されてしまうため注意が必要です。

また、それ以前に、Oracle でキャラクタ・セットを変換してテキストファイルの入出力を行うべきなのか、OS 側で文字コード変換を行うべきなのかを、開発の容易さ、メンテナンス性、パフォーマンスなどを考慮して検討すべきでしょう。

上記の方法はあくまでもできるというだけで必ずしもベストな実装方法とはいえませんから...



【関連エントリ】
[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