Re: Zipping multiple BLOBs
On Feb 23, 10:08 am, Lew <no...@lewscanon.com> wrote:
cdef wrote:
After doing some tweaking and a lot of face-palming, I have reworked
my EXACT code and ended up with EXACTLY this:
CREATE OR REPLACE TYPE res_blob_zip AS TABLE OF BLOB
/
CREATE OR REPLACE TYPE RES_FILE_NAME_NT AS TABLE OF VARCHAR2(2000)
/
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "ZIPImpl" AS
import java.io.*;
import java.util.zip.*;
import java.sql.Blob;
import oracle.sql.ARRAY;
public class ZIPImpl
{
public static void zipBlob(oracle.sql.ARRAY blobList,
oracle.sql.ARRAY nameList, java.sql.Blob[] outBlob) throws Exception
{
Blob[] blobs = (Blob[]) blobList.getArray();
String[] names = (String[]) nameList.getArray();
int blobCount = blobs.length;
int nameCount = names.length;
Blob zipLob = outBlob[0];
Apparently 'outBlob[0]' is 'null'.
When you create a reference (non-primitive) array of a certain length, sa=
y
'n', all n entries are 'null' unless set to a different value explicitly.
OutputStream os = zipLob.setBinaryStream(0);
zipLob = null;
ZipOutputStream zos = new ZipOutputStream(os);
int chunkSize = 32768;
//Now from this source Blob file, we need to get a stre=
am and
then write that stream into Zipped Output
for (int i = 0; i<= (blobCount - 1); i++)
{
Blob src = blobs[i];
//Create a zip entry for the filename
ZipEntry entry = new ZipEntry(names[i]);
zos.putNextEntry(entry);
long len = src.length();
long offset = 1;
byte[] buffer;
while (offset < len)
{
buffer = src.getBytes(offset, chunkSi=
ze);
if (buffer == null)
break;
zos.write(buffer,0,buffer.length);
offset += buffer.length;
}
zos.closeEntry();
}
zos.close();
outBlob[0] = zipLob;
}
}
/
ALTER JAVA CLASS "ZIPImpl" RESOLVE
/
CREATE OR REPLACE PACKAGE res_zip
IS
PROCEDURE zipBlob(blob_list IN res_blob_zip,
name_list IN res_file_name_=
nt,
blob_zip OUT BLOB);
END res_zip;
/
CREATE OR REPLACE PACKAGE BODY res_zip
IS
PROCEDURE zipBlob(blob_list IN res_blob_zip,
name_list IN res_file_name_=
nt,
blob_zip OUT BLOB)
AS LANGUAGE JAVA
NAME
'ZIPImpl.zipBlob(oracle.sql.ARRAY,oracle.sql.ARRAY,java.sql.Blob[])';
END res_zip;
/
I have reworked my PL/SQL code to call the procedure zipBlob exactly
ONE time after filling the blob and filename tables to pass in as
arrays
res_zip.zipBlob(blob_list,name_list,blob_zip);
My issue now is that I am receiving the following error caused by the
declaration of "OutputStream os = zipLob.setBinaryStream(0);" in the
Java code:
Java call terminated by uncaught Java exception:
java.lang.NullPointerException
From the error message one can see that 'zipLob' is 'null'. If you
dereference a 'null' pointer (a.k.a. reference) you get that exception.
I have tried "OutputStream os = zipLob.setBinaryStream(1);" as well a=
s
You still have to set 'zipLob' to a non-'null' value first.
declaring zipBlob [sic] as "Blob zipLob = blobs[0];", and "Blob zipLo=
b =
null;" but I still receive the error.
Sure, because both those assignments must be (and the second one explicit=
ly
is) assigning 'null' to 'zipLob'. In order to dereference a pointer
successfully it must be non-'null'.
--
Lew
Thanks, that was indeed the issue. The solution that worked for me was
to create a temporary blob. This also addressed another issue with
Java/Oracle attempting to overwrite the BLOB in the table with the new
zip BLOB.
In case anyone else runs into this in the future, here is my working,
somewhat finalized code (still could use a little cleanup):
CREATE OR REPLACE JAVA SOURCE NAMED "ZIPImpl" AS
import java.io.*;
import java.util.zip.*;
import java.sql.Blob;
import oracle.sql.ARRAY;
import oracle.sql.*;
import java.sql.*;
import oracle.jdbc.*;
public class ZIPImpl {
public static void zipBlob(oracle.sql.ARRAY
blobList,oracle.sql.ARRAY nameList,java.sql.Blob[] outBlob) throws
Exception {
Connection conn =
DriverManager.getConnection("jdbc:default:connection:");
Blob[] blobs = (Blob[]) blobList.getArray();
String[] names = (String[]) nameList.getArray();
int blobCount = blobs.length;
int nameCount = names.length;
Blob zipLob = BLOB.createTemporary(conn, false,
BLOB.DURATION_SESSION);
OutputStream os = zipLob.setBinaryStream(1);
ZipOutputStream zos = new ZipOutputStream(os);
int chunkSize = 32768;
//Now from this source Blob file, we need to get a stream and
then write that stream into Zipped Output
for (int i = 0; i<= (blobCount - 1); i++) {
Blob src = blobs[i];
//Create a zip entry for the filename
ZipEntry entry = new ZipEntry(names[i]);
zos.putNextEntry(entry);
long len = src.length();
long offset = 1;
byte[] buffer;
while (offset < len) {
buffer = src.getBytes(offset, chunkSize);
if (buffer == null)
break;
zos.write(buffer,0,buffer.length);
offset += buffer.length;
}
zos.closeEntry();
}
zos.close();
outBlob[0] = zipLob;
}
}
/
Thanks to all who had the patience to help me with this. I really do
appreciate it.