Top > XT_PACKAGE > XT_UTL_FILE (バイナリファイル・アクセス)
PL/SQL からバイナリファイルを書き込む
|
| 対象 | ファイル名 | 漢字コード |
| Java および PL/SQL パッケージファイル | Shift JIS | |
| Oracle 9i 用(FileChannel未使用) | Shift JIS |
クラス名: jp.rivus.io.UtilFileSurrogate
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED XT_UTL_FILE_PEER AS package jp.rivus.io; import java.io.FileOutputStream; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import oracle.sql.BLOB; class UtilFileSurrogate { public final static int DEBUG_LEVEL = 1; public final static int SUCCESS = 0; public final static int FAIL = 1; public final static int MULTI_WRITE_COUNT = 8; /** * writeBlob to file. * @return SUCCESS(0) if the LOB is written. / FAIL(1) errors */ public static int writeBlob(String pFilename, BLOB pBlob) throws Exception { int len = -1; int ret = FAIL; // (default) FileOutputStream fos = null; FileChannel channel = null; ByteBuffer channelBuffer = null; try{ int chunk = MULTI_WRITE_COUNT * pBlob.getChunkSize(); InputStream bis = pBlob.getBinaryStream(); fos = new FileOutputStream(pFilename); channel = fos.getChannel(); byte[] buffer = new byte[chunk]; while((len = bis.read(buffer))!=-1){ channelBuffer = ByteBuffer.wrap(buffer,0,len); channel.write(channelBuffer); } ret = SUCCESS; } catch (Exception e) { // hadleException(e); if (DEBUG_LEVEL > 0) e.printStackTrace(); } finally { try { if(fos != null) fos.close(); } catch (Exception e) { // nop } } return ret; } } /Java ストアド・プロシージャをコンパイルさせるときには & や && が置換記号扱いされる。 ソースコードの投入前に以下のコマンドを実行しておく。(このソースには & が無いので関係ない)
-- 置換文字(&)を無効化する SQL> SET DEFINE OFF参考: DEFINE システム変数
XT_UTL_FILE パッケージ
CREATE OR REPLACE PACKAGE RIVUS.XT_UTL_FILE IS -- -- PUT_BLOB FUNCTION PUT_BLOB(P_FILE IN VARCHAR2, P_BLOB IN OUT NOCOPY BLOB) RETURN NUMBER; -- -- PUT_CLOB FUNCTION PUT_CLOB(P_FILE IN VARCHAR2, P_CLOB IN OUT NOCOPY CLOB, P_CSNAME IN VARCHAR2:=NULL) RETURN NUMBER; -- -- PUT_CHAR FUNCTION PUT_CHAR(P_FILE IN VARCHAR2, P_CHAR IN VARCHAR2, P_CSNAME IN VARCHAR2:=NULL) RETURN NUMBER; -- -- PUT_RAW FUNCTION PUT_RAW(P_FILE IN VARCHAR2, P_RAW IN RAW) RETURN NUMBER; END; / CREATE OR REPLACE PACKAGE BODY RIVUS.XT_UTL_FILE IS -- Java Stored Package Peer FUNCTION PUT_BLOB_PEER(P_FILE IN VARCHAR2, P_BLOB IN BLOB) RETURN NUMBER AS LANGUAGE JAVA NAME 'jp.rivus.io.UtilFileSurrogate.writeBlob(java.lang.String, oracle.sql.BLOB) return java.lang.String'; -- -- PUT_BLOB FUNCTION PUT_BLOB(P_FILE IN VARCHAR2, P_BLOB IN OUT NOCOPY BLOB) RETURN NUMBER IS BEGIN -- DBMS_JAVA.SET_OUTPUT(2000); -- printStackTrace -> DBMS_OUTPUT RETURN XT_UTL_FILE.PUT_BLOB_PEER(P_FILE, P_BLOB); END; -- -- PUT_CLOB FUNCTION PUT_CLOB(P_FILE IN VARCHAR2, P_CLOB IN OUT NOCOPY CLOB, P_CSNAME IN VARCHAR2:=NULL) RETURN NUMBER IS vRet NUMBER; vBlob BLOB; vDstOffset INTEGER := 1; -- Dest Offset vSrcOffset INTEGER := 1; -- Source Offset vCSID NUMBER; -- Charset ID vLangContext INTEGER := DBMS_LOB.DEFAULT_LANG_CTX; -- Lang Context vWarning INTEGER := DBMS_LOB.NO_WARNING; -- Warning BEGIN vCSID := NVL(CASE WHEN P_CSNAME IS NOT NULL THEN NLS_CHARSET_ID(P_CSNAME) ELSE DBMS_LOB.DEFAULT_CSID END, DBMS_LOB.DEFAULT_CSID); DBMS_LOB.CREATETEMPORARY(vBlob, TRUE, DBMS_LOB.CALL); -- BLOB 初期化 DBMS_LOB.CONVERTTOBLOB(vBlob, P_CLOB, DBMS_LOB.LOBMAXSIZE, vDstOffset, vSrcOffset, vCSID, vLangContext, vWarning); vRet := XT_UTL_FILE.PUT_BLOB(P_FILE, vBlob); DBMS_LOB.FREETEMPORARY(vBlob); RETURN vRet; END; -- -- PUT_CHAR FUNCTION PUT_CHAR(P_FILE IN VARCHAR2, P_CHAR IN VARCHAR2, P_CSNAME IN VARCHAR2:=NULL) RETURN NUMBER IS vClob CLOB; BEGIN vClob := P_CHAR; RETURN XT_UTL_FILE.PUT_CLOB(P_FILE, vClob, P_CSNAME); END; -- -- PUT_RAW FUNCTION PUT_RAW(P_FILE IN VARCHAR2, P_RAW IN RAW) RETURN NUMBER IS vBlob BLOB; BEGIN vBlob := P_RAW; RETURN XT_UTL_FILE.PUT_BLOB(P_FILE, vBlob); END; END XT_UTL_FILE; /
RIVUS ユーザへの権限の付与と削除例
-- Grant (付与) SQL> CALL DBMS_JAVA.GRANT_PERMISSION('RIVUS', 'java.io.FilePermission', 'c:\hoge.dat', 'read,write'); -- Revoke (削除) SQL> CALL DBMS_JAVA.REVOKE_PERMISSION('RIVUS', 'java.io.FilePermission', 'c:\hoge.dat', 'read,write'); -- Grant UTL_FILE_DIR = * と同じレベル SQL> CALL DBMS_JAVA.GRANT_PERMISSION('RIVUS', 'java.io.FilePermission', '<<ALL FILES>>', 'read,write');CREATE DIRECTORY や UTL_FILE_DIR 初期化パラメータのように再起動が必要になったり、動的 SQL を用いることなくプログラム内においても DIRECTORY オブジェクト管理に比べて低い権限でかつダイナミックに書き込み権限の作成、付与および削除が行ないやすいためセキュリティリスクが高くなる可能性がある。
SQL*Plus で実行
デフォルトのキャラクタセットはデータベースのキャラクタセットになる。
DECLARE vRet NUMBER; BEGIN -- 常に上書きされるので最後の1行だけ残る。 vRet := XT_UTL_FILE.PUT_CHAR('c:\hoge.txt', 'あいうえお'); vRet := XT_UTL_FILE.PUT_CHAR('c:\hoge.txt', 'かきくけこ', 'JA16SJISTILDE'); vRet := XT_UTL_FILE.PUT_CHAR('c:\hoge.txt', 'さしすせそ', 'JA16EUCTILDE'); vRet := XT_UTL_FILE.PUT_CHAR('c:\hoge.txt', 'たちつてと', 'AL16UTF16'); vRet := XT_UTL_FILE.PUT_CHAR('c:\hoge.txt', 'なにぬねの', 'AL32UTF8'); END; /
DECLARE vRet NUMBER; BEGIN vRet := XT_UTL_FILE.PUT_RAW('c:\hoge.txt', HEXTORAW('303132333435')); DBMS_OUTPUT.PUT_LINE(vRet); END; /
DECLARE vRet NUMBER; vClob CLOB; BEGIN vClob := RPAD('X', 32*1024-1, 'X'); vClob := vClob || RPAD('Y', 32*1024-1, 'Y'); vRet := XT_UTL_FILE.PUT_CLOB('c:\hoge.txt', vClob, 'AL16UTF16'); DBMS_OUTPUT.PUT_LINE(vRet); END; /