Re: JDBC Large Object getBinaryStream returns -1 before EOF

From: "Akira Kumakiri" <kumakiri(at)ekuma(dot)net>
To: <pgsql-bugs(at)postgresql(dot)org>
Subject: Re: JDBC Large Object getBinaryStream returns -1 before EOF
Date: 2001-08-18 10:32:49
Message-ID: 000801c127d1$21a51680$de09713d@ekuma.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Oops, sorry.

Red Hat Linux 6.2J (Japanese); that's the reason why added >java lobtest -s
guessed encoding caused this error...
Postgresql-7.1.2 (not RPM, separately installed one.)
$ ./configure --enable-multibyte=EUC_JP --with-java are used.
jdk1.2.2
Intel Pentium-2 processor

----- Original Message -----
From: "Akira Kumakiri" <kumakiri(at)ekuma(dot)net>
To: <pgsql-bugs(at)postgresql(dot)org>
Sent: Saturday, August 18, 2001 6:55 PM
Subject: [BUGS] JDBC Large Object getBinaryStream returns -1 before EOF

> Hi,
>
> I'm making some code handling several kinds of files as large object. I found
the
> JDBC driver returned without finish reading the file. I made the test program
> named lobtest.java, which is added at the end of this mail.
>
> This test program read a file (default is "tomcat.gif" which is fetched from
> Tomcat home page, but you can specify the name.), and write it into data base
> named "lobtest". And then read it just after writing. But the size between the
> original one and write/read one is different. Everytime, the file after
> write/read is smaller.
>
> Some one in Postgres Mailing List in Japan ( pgsql-jp(at)sra(dot)co(dot)jp ) found the same
> problem and checked inside the JDBC driver source code. He thinks read() in
> BlobInputStream.java has something wrong at the following part, then changed a
> liitle bit, and worked fine. He says he does not know all the JDBC driver
codes,
> and is not clear whether this is the correct fix or not.
>
> The following is the part of org/postgresql/largeobject/BlobInputStream.java
>
> /**
> * The minimum required to implement input stream
> */
> public int read() throws java.io.IOException {
> try {
> if(buffer==null || bpos>=buffer.length) {
> buffer=lo.read(bsize);
> bpos=0;
> }
>
> // Handle EOF
> if(bpos>=buffer.length)
> return -1;
>
> int tmp = (int)buffer[bpos++]; //**** originally return
> (int)buffer[bpos++];
> if (tmp<0) tmp = tmp+256; //**** but, replaced using tmp as left side
> shows.
> return tmp; //**** and worked fine.
> } catch(SQLException se) {
> throw new IOException(se.toString());
> }
> }
>
> You can reproduce this by the follwoing steps.
>
> 1) > createdb lobtest
>
> 2) >psql lobtest
> lobtest=# CREATE TABLE tests (
> index serial,
> imgname text,
> imgoid oid
> );
>
> 3) copy the following test program into file (lobtest.java), then compile it.
> Some unexpected CR may be added by mailer. Please remove these.
>
> 4) type >java lobtest -i foo.gif
> or whatever file you have on the same directory as lobtest.class file.
> From my experience, all the gif file causes an error.
> > java lobtest ? shows help.
>
> 5) lobtest reads file, stores it onto db as large object, then reads it again,
and
> writes it on the same directory. If the file is tomcat.gif, then r_tomcat.gif
is
> created. Please check the file size on both.
>
> 6) If I use getBytes("imgoid"), then no error.
>
> Thank you for reading my poor English.
>
> akira (ricky(at)ekuma(dot)net or kumakiri(at)ekuma(dot)net )
>
> /*
> * lobtest.java
> *
> */
>
> import java.io.*;
> import java.lang.*;
> import java.sql.*;
> import java.util.*;
> import sun.io.*;
>
> class lobtest {
> static String index = null;
> static String filename = "tomcat.gif";
> static String url = "jdbc:postgresql:lobtest";
> static String account = "postgres";
> static String password = "postgrespassword";
> public static void main(String argv[]) {
> for (int optind = 0; optind < argv.length; optind++) {
> if (argv[optind].equals("-i")) {
> filename = argv[++optind];
> } else if (argv[optind].equals("-s")) {
> System.out.println("System default encoding = "
> +System.getProperty("file.encoding"));
> System.out.println("ByteToCharConverter= "
> +ByteToCharConverter.getDefault());
> System.out.println("CharToByteConverter= "
> +CharToByteConverter.getDefault());
> System.exit(0);
> } else if (argv[optind].equals("--")) {
> optind++;
> break;
> } else if (argv[optind].startsWith("?")) {
> System.out.println("Usage: test [-i file] [-s] [?]");
> System.out.println(" (no param), write large object on db, and
read
> it, then compare it.");
> System.out.println(" -i file, specify file name, default is
> tomcat.gif");
> System.out.println(" -s show system parameters");
> System.out.println(" ? show this help");
> System.exit(0);
> } else break;
> }
>
> try { // establish DB connections.
> Class.forName("org.postgresql.Driver");
> } catch(ClassNotFoundException cnf) {
> cnf.printStackTrace();
> System.out.println("Class.forName() error.");
> System.exit(1);
> }
>
> // Starting...
> // Write file into DB as Large Object.
> String query = null;
> int length = 0;
> Connection connM = null;
> byte[] byteArray = null;
> try {
> File file = new File(filename);
> FileInputStream fis = new FileInputStream(file);
> int c = fis.available();
> byteArray = new byte[c];
> int get = fis.read(byteArray);
> fis.close();
> length = byteArray.length;
> System.out.println("c= " +c +" get= " +get +" byteArray.length= "
+length);
>
> connM = DriverManager.getConnection(url, account, password);
> connM.setAutoCommit(false);
> InputStream bis = new ByteArrayInputStream(byteArray);
> query = "INSERT INTO tests (imgname, imgoid) VALUES ('" +filename +"',
?);";
> PreparedStatement ps = connM.prepareStatement(query);
> ps.setBinaryStream(1, bis, length);
> int result = ps.executeUpdate();
> connM.commit();
> ps.close();
> bis.close();
> System.out.println("filename= " +filename +" file.length= " +length +"
> result= " +result);
> } catch(SQLException sql) {
> sql.printStackTrace();
> } catch(FileNotFoundException fnf) {
> fnf.printStackTrace();
> } catch(IOException ioe) {
> ioe.printStackTrace();
> } finally {
> try {
> connM.setAutoCommit(true);
> } catch (Exception againse) {
> System.out.print("write Exception again at setAutoCommit(true)");
> System.exit(1);
> }
> }
>
>
> // The follwoing is the way to read large object using InputStream, but
> unexpected -1 returns.
> // BlobInputStream.java causes the error ???.
> try {
> connM.setAutoCommit(false);
> query = "SELECT imgoid FROM tests WHERE imgname='" +filename +"';";
> Statement st = connM.createStatement();
> ResultSet rs = st.executeQuery(query);
>
> // ****** Case 1 ******
> while(rs.next()) {
> InputStream is = rs.getBinaryStream("imgoid");
> BufferedInputStream bis = new BufferedInputStream(is);
> String pathname = "./r_" +filename;
> File file = new File(pathname);
> boolean del = file.delete(); // test this again and again, so delete
old
> one.
> if ( ! file.canRead()) { // always false. debugging now.
> FileOutputStream fos = new FileOutputStream(file);
> int c; // stream may return 0 when the method available() is
called.
> int i = 0;
> while ((c=bis.read()) != -1) {fos.write(c); ++i;}// don't use
> available() see java.sql
> fos.close();
> System.out.println("total read bytes i= " +i);
> bis.close();
> }
> }
>
> // ***** Case 2 *****
> // You can avoid the above error by using getBytes() instead.
> /* while(rs.next()) {
> byte[] stb = rs.getBytes("imgoid");
> String pathname = "./r_" +filename;
> File file = new File(pathname);
> boolean del = file.delete(); // test this again and again, so delete
old
> one.
> if ( ! file.canRead()) { // always false. debugging now.
> FileOutputStream fos = new FileOutputStream(file);
> fos.write(stb);
> fos.close();
> System.out.println("total read bytes stb.length= " +stb.length);
> }
> } */
>
> connM.commit();
> rs.close();
> st.close();
> } catch(SQLException sql) {
> sql.printStackTrace();
> } catch(IOException ioe) {
> ioe.printStackTrace();
> } finally {
> try {
> connM.setAutoCommit(true);
> } catch (Exception againse) {
> System.out.print("read Exception again at setAutoCommit(true)");
> System.exit(1);
> }
> }
>
> }
>
> } // class end.
>
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
> (send "unregister YourEmailAddressHere" to majordomo(at)postgresql(dot)org)
>

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Hans-Jürgen Schönig 2001-08-19 09:40:24 Building 7.1.3 with PL/Perl support on RedHat
Previous Message Akira Kumakiri 2001-08-18 09:55:03 JDBC Large Object getBinaryStream returns -1 before EOF