简体   繁体   中英

Image to ByteArray to BLOB and BLOB to ByteArray to Image Conversion Issues in Java

After a lot of learning on ByteArrays & BLOBS, I managed to write the below Java code to write an image into Access DB (Using ucanaccess) and writing it back to Disk.

When I write an image back to disk the image is in incorrect format or something is messed up that you cannot open that image.

I understand it is not a good practice to store Images on DB but, this is only for my learning.

public static void Update_to_DB() throws SQLException, IOException {
    String URL = "jdbc:ucanaccess://C:\\Users\\bharat.nanwani\\Desktop\\Images.accdb";
    Connection conn = DriverManager.getConnection(URL);
    //Statement stmt = conn.createStatement();
    PreparedStatement p;

    File ImgPath = new File("C:\\Users\\bharat.nanwani\\Desktop\\Desert.jpg");
    BufferedImage bufferedimage = ImageIO.read(ImgPath);

    WritableRaster raster = bufferedimage.getRaster();
    DataBufferByte data = (DataBufferByte) raster.getDataBuffer();

    byte[] bytearray = date.getdata();


    String query = "INSERT INTO Images(data) VALUES(?);";
    p = conn.prepareStatement(query);
    p.setBinaryStream(1, new ByteArrayInputStream(bytearray),bytearray.length);
    p.execute();
}

public static void update_to_DISK() throws SQLException, IOException {
        String URL = "jdbc:ucanaccess://C:\\Users\\bharat.nanwani\\Desktop\\Images.accdb";
        Connection conn = DriverManager.getConnection(URL);
        PreparedStatement p;
        ResultSet rs;
        String query = "SELECT Data FROM Images";
                p=conn.prepareStatement(query);
        rs = p.executeQuery();
        if (rs.next()) {
        Blob blob = rs.getBlob("Data");

        byte[] bytearray = blob.getBytes(1L, (int)blob.length());

        FileOutputStream fos = new FileOutputStream("C:\\Users\\bharat.nanwani\\Desktop\\New Folder\\test.jpg");
        fos.write(bytearray);
        fos.close();

        System.out.println(bytearray);
        } 
    }

Firstly, you should separate this into two parts:

  • Storing binary data in a database and retrieving it
  • Loading an image file and saving it again

There's no need to use a database to test the second part - you should diagnose the issues by loading the image and saving straight to a file, skipping the database.

No, I believe the problem is that you're copying the data from the WritableRaster's databuffer, and then saving that to a .jpg file. It's not a jpeg at that point - it's whatever the internal format of the WritableRaster uses.

If you want a jpeg file, you don't need to use ImageIO at all - because you've started off with a jpeg file. If you want to start and end with the same image, just copy the file (or save the file to the database, in your case). That's just treating the file as bytes.

If you need to do something like saving in a different format, or at a different size, etc, then you should ask the ImageIO libraries to save the image as a JPEG again, re-encoding it... and then store the result as a file or in the database etc.

Below is what I'm doing to write to DB -

public static void main(String[] Args) throws SQLException, IOException {
    String URL = "jdbc:ucanaccess://C:\\Users\\bharat.nanwani\\Desktop\\Images.accdb";
    Connection conn = DriverManager.getConnection(URL);
    PreparedStatement p;

    File ImgPath = new File("C:\\Users\\bharat.nanwani\\Desktop\\Desert.jpg");
    FileInputStream fileinput = new FileInputStream(ImgPath); 

    byte[] bytearray = new byte[(int)ImgPath.length()];


    String query = "INSERT INTO Images(data) VALUES(?);";
    p = conn.prepareStatement(query);
    //p.setBinaryStream(1, new ByteArrayInputStream(bytearray),bytearray.length);
    p.setBytes(1, bytearray);
    p.execute();
}

read the image file using FileInputStream rather than WritableRaster

and then store Image file in database using setBinaryStream() method of PreparedStatement ..

it will store the file in bytes.

also while getting file back from database use getBytes() method of ResultSet and store it using FileOutputStream

public static void Update_to_DB() throws SQLException, IOException {
    String URL = "jdbc:ucanaccess://C:\\Users\\bharat.nanwani\\Desktop\\Images.accdb";
    Connection conn = DriverManager.getConnection(URL);
    //Statement stmt = conn.createStatement();
    PreparedStatement p;

    File ImgPath = new File("C:\\Users\\bharat.nanwani\\Desktop\\Desert.jpg");
    FileInputStream fin = new FileInputStream(ImgPath);
    String query = "INSERT INTO Images(Data) VALUES(?);";
    p = conn.prepareStatement(query);
    p.setBinaryStream(1, fin);
    p.execute();
}

public static void update_to_DISK() throws SQLException, IOException {
    String URL = "jdbc:ucanaccess://C:\\Users\\bharat.nanwani\\Desktop\\Images.accdb";
    Connection conn = DriverManager.getConnection(URL);
    PreparedStatement p;
    ResultSet rs;
    String query = "SELECT Data FROM Images";
    p = conn.prepareStatement(query);
    rs = p.executeQuery();
    if (rs.next()) {
        byte[] bytearray = rs.getBytes("Data");
        FileOutputStream fos = new FileOutputStream("C:\\Users\\bharat.nanwani\\Desktop\\New Folder\\test.jpg");
        fos.write(bytearray);
        fos.close();
        System.out.println(bytearray);
    }
}

it will solve your problem..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM