Re: JDBC Large Object getBinaryStream returns -1 before EOF

Поиск
Список
Период
Сортировка
От Akira Kumakiri
Тема Re: JDBC Large Object getBinaryStream returns -1 before EOF
Дата
Msg-id 000801c127d1$21a51680$de09713d@ekuma.net
обсуждение исходный текст
Ответ на JDBC Large Object getBinaryStream returns -1 before EOF  ("Akira Kumakiri" <kumakiri@ekuma.net>)
Список 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@ekuma.net>
To: <pgsql-bugs@postgresql.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@sra.co.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@ekuma.net or kumakiri@ekuma.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@postgresql.org)
>

В списке pgsql-bugs по дате отправления:

Предыдущее
От: "Akira Kumakiri"
Дата:
Сообщение: JDBC Large Object getBinaryStream returns -1 before EOF
Следующее
От: pgsql-bugs@postgresql.org
Дата:
Сообщение: ecpg 2.8.0 fails to handle struct properly