« Mac De Oracle (PL/SQL De UNCOMPRESS) | トップページ | APEX! »

2006年8月29日 (火)

Mac De Oracle (PL/SQL De COMPRESS)

解凍につづき、圧縮を試す。


まずは gzip するテキストファイルは前回準備しておいたものを利用する。このテキストファイルをcompressed_file.gzとして圧縮してみる。尚、UTL_COMPRESS.LZ_COMPRESS()では、圧縮レベルが1〜9あり、デフォルトは、6。最も圧縮率が高いのは、9。この例では、圧縮率=6(デフォルト)で圧縮する。

G5Server:˜ oracle$ ls -l
total 48096
中略
-rw-r--r-- 1 oracle oinstall 559 Aug 20 06:35 org.txt
中略
G5Server:˜ oracle$
G5Server:˜ oracle$ cat org.txt
操作上の注意
■ LZ* ファンクションによって戻された一時 LOB は、コール元が
DBMS_ LOB.FREETEMPORARY コールを使用して解放する必要があります。
■ LZ_COMPRESS* または LZ_UNCOMPRESS* に渡された BFILE は、
DBMS_LOB.FILEOPENでオープンする必要があります。
■ 特別な状況(入力がすでに圧縮されている場合)では、UTL_COMPRESS サブプログラムの
1 つで生成された出力が、入力と同じ大きさかまたは入力よりもわずかに大きくなる
ことがあります。
■ UTL_COMPRESS で圧縮したデータの出力は、1 つのファイル上の gzip(-n オプション を指定)/gunzip と
互換性があります。
G5Server:˜ oracle$

早速取りかかる。今回も Oracle SQL Developer 1.0 for MacOSXを利用する。

だ〜〜〜〜っと、前回のコードを少々修正して実行(無名PL/SQLブロックにしてあるが、ストアドプロシージャでもファンクションでも、パッケージで実装しても全く問題はない。尚、事前にディレクトリオブジェクトは作成してある。)
Macdecompress1_1

圧縮ファイル(compressed_file.gz)が正しく作成できたか確認する。

G5Server:˜ oracle$ ls -l
total 48112
中略
-rw-r--r-- 1 oracle oinstall 408 Aug 20 13:11 compressed_file.gz
-rw-r--r-- 1 oracle oinstall 559 Aug 20 06:35 org.txt
中略
G5Server:˜ oracle$
G5Server:˜ oracle$ gunzip -lt compressed_file.gz
compressed uncompressed ratio uncompressed_name
408 559 30.2% compressed_file
G5Server:˜ oracle$
G5Server:˜ oracle$ gunzip -c compressed_file.gz
操作上の注意
■ LZ* ファンクションによって戻された一時 LOB は、コール元が
DBMS_ LOB.FREETEMPORARY コールを使用して解放する必要があります。
■ LZ_COMPRESS* または LZ_UNCOMPRESS* に渡された BFILE は、
DBMS_LOB.FILEOPENでオープンする必要があります。
■ 特別な状況(入力がすでに圧縮されている場合)では、UTL_COMPRESS サブプログラムの
1 つで生成された出力が、入力と同じ大きさかまたは入力よりもわずかに大きくなる
ことがあります。
■ UTL_COMPRESS で圧縮したデータの出力は、1 つのファイル上の gzip(-n オプション を指定)/gunzip と
互換性があります。
G5Server:˜ oracle$

前述のように、gunzipで解凍してしまうのもよいのだが、ダブルクリックして解凍しちゃいましょう。すばらしいGUIがあるんですから。
Macdecompress2_1 Macdecompress3


以下に今回作成したコードを示す。

DECLARE
v_src_text_file BFILE;
v_compressed_blob BLOB;
v_directory_name VARCHAR2(30);
v_src_text_file_name VARCHAR2(510);
v_dest_file_name VARCHAR2(510);

PROCEDURE close_bfile
(
i_bfile IN OUT NOCOPY BFILE
)
IS
BEGIN
IF DBMS_LOB.ISOPEN(i_bfile) = 1 THEN
DBMS_LOB.CLOSE(i_bfile);
END IF;
END close_bfile;

PROCEDURE write_blob_to_file
(
i_directory_name IN VARCHAR2,
i_file_name IN VARCHAR2,
i_src_blob IN OUT NOCOPY BLOB
)
IS
v_file UTL_FILE.FILE_TYPE;
BEGIN
v_file := UTL_FILE.FOPEN(
UPPER(i_directory_name),
i_file_name,
'wb',
32767
);

-- ファイルへ書き出すBLOBはオープンされていることを前提とする
DECLARE
c_chunk_size CONSTANT PLS_INTEGER := 32767;

v_buffer RAW(32767);
v_amount PLS_INTEGER := c_chunk_size;
v_num_of_chunk PLS_INTEGER;
BEGIN
v_num_of_chunk := CEIL(DBMS_LOB.GETLENGTH(i_src_blob)/c_chunk_size);
FOR chunk# IN 1..v_num_of_chunk LOOP
DBMS_LOB.READ(
i_src_blob,
v_amount,
(c_chunk_size * (chunk# - 1)) + 1, /*offset*/
v_buffer
);
UTL_FILE.PUT_RAW(v_file, v_buffer, TRUE);
END LOOP;
END;

UTL_FILE.FCLOSE(v_file);
END write_blob_to_file;
--
BEGIN
-- ディレクトリ名の設定
v_directory_name := 'MYDIR';
-- テキストファイル名
v_src_text_file_name := 'org.txt';
-- 出力ファイル名
v_dest_file_name := 'compressed_file.gz';

DBMS_OUTPUT.PUT_LINE('========== compress start ==========');

-- テキストファイルをBFILEとして開く。
v_src_text_file
:= BFILENAME(UPPER(v_directory_name), v_src_text_file_name);
DBMS_LOB.OPEN(v_src_text_file);

-- BFILEを圧縮し、一時BLOBへ (圧縮品質はデフォルトで圧縮する)
v_compressed_blob := UTL_COMPRESS.LZ_COMPRESS(v_src_text_file);

-- BLOB(圧縮済み)を書き出す
write_blob_to_file(
UPPER(v_directory_name),
v_dest_file_name,
v_compressed_blob
);

-- 一時LOBの解放及び、BFILEのクローズ
DBMS_LOB.FREETEMPORARY(v_compressed_blob);
close_bfile(v_src_text_file);

DBMS_OUTPUT.PUT_LINE('========== compress end ==========');

EXCEPTION
WHEN OTHERS THEN
-- 一時LOBの解放及び、BFILEのクローズ
DBMS_LOB.FREETEMPORARY(v_compressed_blob);
close_bfile(v_src_text_file);
RAISE;
END;
/

OTN JapanCodeTipsに公開してあります。
聞いている曲:
KraftWerk - Minimum - Maximum (live) Kraftwerk - Minimum - Maximum (Live)
Kraftwerk - Minimum - Maximum (Live)

|

トラックバック


この記事へのトラックバック一覧です: Mac De Oracle (PL/SQL De COMPRESS):

コメント

PL/SQL初心者である私に、
知恵をください。

同じディレクトリにある
複数のファイルの同時に圧縮するには、
どうすればよいかご存知でしょうか。

たとえば、以下のようにできれば、
うれしいのですが。

-- ディレクトリ名の設定 v_directory_name := 'MYDIR';

-- 出力ファイル名 v_dest_file_name := 'compressed_file.gz';

FOR COUNT IN 1..5 LOOP
-- テキストファイル名 v_src_text_file_name := 'org'||COUNT||'.txt';
v_src_text_file:= BFILENAME(UPPER(v_directory_name), v_src_text_file_name);
DBMS_LOB.OPEN(v_src_text_file);
UTL_COMPRESS.LZ_COMPRESS(v_src_text_file, v_compressed_blob);

END LOOP;

write_blob_to_file(UPPER(v_directory_name), v_dest_file_name, v_compressed_blob);

投稿: sen_care | 2006年10月15日 (日) 05時26分

sen_careさん、

はじめまして、 discusです。

初心者向けの内容ではないので、質問が来る事をあまり想定していなかったといことも事実なのですが・・・
申し訳ありませんが、当ブログは、QAコーナーとして立ち上げたものではありませんので、基本的に質問にお答えすることは無いとお考えください。
一旦、QAコーナーと化してしまうと収拾つかなくなる可能性もありますので、OTNやその他のオラクル関連Forumへご質問ください。m(_ _)m
(暇な時には、OTNで回答することもありますし。)


ただ、例外として、私が興味を持っている内容でしたら、回答という形式ではなく、それとなくこのブログで記事したり、コメントで返すことも”ごく稀に”あるかもしれません。。

ということで、今回は、その例外だと思ってください。 
gzip/gunzip の通常の使い方を考えれば、 tarでアーカイブしたファイルを Oracleのディレクトリオブジェクト以下に配置し、それを
UTL_COMPRESSで圧縮すれば解決する話だと思いますが? いかがですか? 

==マニュアルより抜粋ここから==
UTL_COMPRESS で圧縮したデータの出力は、1 つのファイル上の gzip(-n オプション を指定)/gunzip と互換性があります。
==マニュアルより抜粋ここまで==

投稿: discus | 2006年10月15日 (日) 18時47分

コメントを書く