Created
December 16, 2011 09:09
-
-
Save seraphy/1485245 to your computer and use it in GitHub Desktop.
ORACLE PL/SQLでUTF8且つBASE64でエンコードされたメールヘッダに使えるような文字列を作成する方法メモ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DECLARE | |
-- UTF8のOracle(NLS)表現 | |
UTF8 constant nvarchar2(250) := 'AL32UTF8'; | |
-- 改行コード | |
CRLF CONSTANT VARCHAR2(2) := chr(13) || chr(10); | |
-- タブコード | |
TAB CONSTANT VARCHAR2(1) := chr(9); | |
/** | |
* 引数に指定した非ASCII文字を含む文字列を、UTF8/BASE64でエンコードし | |
* 80桁以内に収まるように折り返した複数行形式のデータに変換して返す. | |
* 返されたRAW型はASCII文字だけを含んでおり、メールヘッダの値として使用できる. | |
* 末尾に改行コードを付与するか指定することが可能. | |
*/ | |
FUNCTION MAKE_HEADER_VALUE( | |
p_value NVARCHAR2, | |
p_CRLF BOOLEAN := TRUE | |
) RETURN RAW IS | |
-- ヘッダ部のUTF-8/BASE64エンコード開始マーカー | |
ENCMARK constant varchar2(10) := '=?UTF-8?B?'; | |
-- ヘッダ部のエンコード終了マーカー | |
ENCMARK_EN constant varchar2(2) := '?='; | |
-- 変換結果 (32KiBが最大) | |
ret RAW(32767); | |
BEGIN | |
DECLARE | |
-- エンコード後のヘッダ行を1行80byteに納めるための分割文字数 | |
-- UTF8なので日本語は3バイト程度に膨らむことを想定 (サロゲートペアは考慮外) | |
-- BASE64なので1.333倍に膨らむことを想定 | |
CHUNKSIZE CONSTANT PLS_INTEGER := 12; | |
-- 入力データ(p_value)の文字数 | |
MXLEN CONSTANT PLS_INTEGER := LENGTH(p_value); | |
-- 現在処理中の桁 | |
pos PLS_INTEGER := 1; | |
-- 1行ごとに処理する対象文字列の切り出しバッファ | |
linechunk NVARCHAR2(12); | |
-- BASE64エンコード処理用バッファ | |
rawdata RAW(80); | |
BEGIN | |
LOOP | |
-- すべて処理したらループ終了 | |
EXIT WHEN pos > MXLEN; | |
-- 分割後であれば改行+タブ | |
IF pos > 1 THEN | |
ret := UTL_RAW.CONCAT( | |
ret, | |
UTL_I18N.STRING_TO_RAW(CRLF || TAB, UTF8) | |
); | |
END IF; | |
-- 分割文字列の取得 | |
linechunk := substr(p_value, pos, CHUNKSIZE); | |
-- UTF8に変換 | |
rawdata := UTL_I18N.STRING_TO_RAW(linechunk, UTF8); | |
IF rawdata IS NULL THEN | |
RAISE_APPLICATION_ERROR(-20101, 'UTF8に変換できません。', FALSE); | |
END IF; | |
-- 出力 | |
ret := UTL_RAW.CONCAT( | |
ret, | |
UTL_I18N.STRING_TO_RAW(ENCMARK, UTF8), | |
UTL_ENCODE.BASE64_ENCODE(rawdata), | |
UTL_I18N.STRING_TO_RAW(ENCMARK_EN, UTF8) | |
); | |
-- 次の位置へ進む | |
pos := pos + chunksize; | |
END LOOP; | |
IF p_CRLF THEN | |
-- 改行終端 | |
ret := UTL_RAW.CONCAT( | |
ret, | |
UTL_I18N.STRING_TO_RAW(CRLF, UTF8) | |
); | |
END IF; | |
END; | |
RETURN ret; | |
END; | |
BEGIN | |
DECLARE | |
vHANDLE UTL_FILE.FILE_TYPE; | |
BEGIN | |
vHANDLE := UTL_FILE.FOPEN('TEMP_DIR', 'hello.txt', 'wb'); | |
UTL_FILE.PUT_RAW( | |
vHANDLE, | |
MAKE_HEADER_VALUE('Hello, World! こんにちは世界!!') | |
); | |
UTL_FILE.FCLOSE(vHANDLE); | |
EXCEPTION WHEN OTHERS THEN | |
UTL_FILE.FCLOSE_ALL; | |
END; | |
END; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment