java代码将16进制字符串转换为图片,jdbc入库blob字段,解决ORA-01704,PLS-00172,ORA-06550,字符串文字太长等问题

从Oracle导出SQL文件中的insert语句包含blob字段,语句HEXTORAW函数将16进制的字符串入库,由于字符串太长,insert失败

下面的代码读取完整的insert语句,将HEXTORAW函数连同16进制的字符串替换为NULL,先将字段置空插入记录,然后使用PreparedStatement对图片文件读流更新入库

import org.apache.commons.io.FileUtils;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

public class ImageUtils {

    public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException {
        File file = new File("C:\\Users\\Nihaorz\\Desktop\\b_file_insert.sql");
        List<String> list = FileUtils.readLines(file, "UTF-8");
        for (String s : list) {
            String imageFilePath = null;
            String id = null;
            String[] array = s.split(",");
            StringBuilder sb = new StringBuilder();
            for (String s1 : array) {
                if (s1.startsWith(" HEXTORAW(")) {
                    id = sb.toString();
                    id = id.substring("INSERT INTO \"B_FILE\" VALUES ('".length());
                    id = id.substring(0, id.indexOf("'"));
                    sb.append(" NULL");
                    String hexString = s1.trim();
                    hexString = hexString.substring("HEXTORAW('".length(), hexString.length() - 1);
                    imageFilePath = "C:\\Users\\Nihaorz\\Desktop\\b_file_images\\" + id + ".jpg";
                    hexToImage(imageFilePath, hexString);
                } else {
                    sb.append(s1);
                }
                sb.append(",");
            }
            sb.deleteCharAt(sb.length() - 1);
            sb.deleteCharAt(sb.length() - 1);
            insert2Kingbase(sb.toString(), imageFilePath, id);
        }
    }

    public static boolean insert2Oracle(String insertSql, String imgPath, String id) throws ClassNotFoundException, SQLException, FileNotFoundException {
        boolean flag = false;
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@x.x.x.x:1521:orcl", "xxx", "xxx");
        conn.createStatement().execute(insertSql);
        // 打印除blob字段之外的insert语句
        System.out.println(insertSql);
        String sql = "update b_file set file_tx = ? where file_id = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        InputStream is = new FileInputStream(imgPath);
        pstmt.setBlob(1, is);
        //还可以通过二进制流的方法存放图片pstmt.setBinaryStream(1,is);
        pstmt.setString(2, id);
        int i = pstmt.executeUpdate();
        if (i > 0) {
            flag = true;
            System.out.println("插入图片成功");
        } else {
            System.out.println("插入图片失败");
        }
        close(pstmt, conn, is);
        return flag;
    }

    public static boolean insert2Kingbase(String insertSql, String imgPath, String id) throws ClassNotFoundException, SQLException, FileNotFoundException {
        boolean flag = false;
        Class.forName("com.kingbase8.Driver");
        Connection conn = DriverManager.getConnection("jdbc:kingbase8://x.x.x.x:54321/xxx", "xxx", "xxx");
        conn.createStatement().execute(insertSql);
        // 打印除blob字段之外的insert语句
        System.out.println(insertSql);
        String sql = "update b_file set file_tx = ? where file_id = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        InputStream is = new FileInputStream(imgPath);
        pstmt.setBlob(1, is);
        //还可以通过二进制流的方法存放图片pstmt.setBinaryStream(1,is);
        pstmt.setString(2, id);
        int i = pstmt.executeUpdate();
        if (i > 0) {
            flag = true;
            System.out.println("插入图片成功");
        } else {
            System.out.println("插入图片失败");
        }
        close(pstmt, conn, is);
        return flag;
    }

    private static void close(AutoCloseable... closeables) {
        for (AutoCloseable autoCloseable : closeables) {
            if (autoCloseable != null) {
                try {
                    autoCloseable.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 将图片转换成十六进制字符串
     */
    static String imageToHex(String filePath) {
        File f = new File(filePath);
        String suffix = filePath.substring(filePath.lastIndexOf(".") + 1);
        BufferedImage bi;
        try {
            bi = ImageIO.read(f);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(bi, suffix, baos);
            byte[] bytes = baos.toByteArray();
            return new BigInteger(1, bytes).toString(16);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将十六进制字符串转化成图片
     */
    static void hexToImage(String filePath, String hexString) {
        byte[] bytes = stringToByte(hexString);
        try {
            FileImageOutputStream imageOutput = new FileImageOutputStream(new File(filePath));
            imageOutput.write(bytes, 0, bytes.length);
            imageOutput.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static byte[] stringToByte(String s) {
        int length = s.length() / 2;
        byte[] bytes = new byte[length];
        for (int i = 0; i < length; i++) {
            bytes[i] = (byte) ((Character.digit(s.charAt(i * 2), 16) << 4) | Character.digit(s.charAt((i * 2) + 1), 16));
        }
        return bytes;
    }

}

 

b_file_insert.sql 示例,HEXTORAW('xxxxxx') 仅做示例,正常的是合法的16进制字符串

INSERT INTO "B_FILE" VALUES ('f7fb0c74-8bdc-4edd-8bae-14e9b923c1c0', '长安.jpg', 'image/jpeg', '510368', NULL, HEXTORAW('xxxxxx'), TO_TIMESTAMP('2020-11-22 22:43:54.780000', 'SYYYY-MM-DD HH24:MI:SS:FF6'), '标准地图')
INSERT INTO "B_FILE" VALUES ('ca6a7638-7ab5-437d-a486-f354fd210308', '麻涌.jpg', 'image/jpeg', '441326', NULL, HEXTORAW('xxxxxx'), TO_TIMESTAMP('2020-11-22 22:46:23.792000', 'SYYYY-MM-DD HH24:MI:SS:FF6'), '标准地图')
INSERT INTO "B_FILE" VALUES ('df5be551-653e-4640-bfd6-7581cdce36fb', '洪梅.jpg', 'image/jpeg', '394404', NULL, HEXTORAW('xxxxxx'), TO_TIMESTAMP('2020-11-22 22:48:19.201000', 'SYYYY-MM-DD HH24:MI:SS:FF6'), '标准地图')
INSERT INTO "B_FILE" VALUES ('abe056c6-d2a5-41b6-bc96-a05e6364b59b', '道滘.jpg', 'image/jpeg', '480304', NULL, HEXTORAW('xxxxxx'), TO_TIMESTAMP('2020-11-22 22:48:58.139000', 'SYYYY-MM-DD HH24:MI:SS:FF6'), '标准地图')
INSERT INTO "B_FILE" VALUES ('7c99a74a-f8c4-4cdc-9e59-6735564bc126', '黄江.jpg', 'image/jpeg', '554472', NULL, HEXTORAW('xxxxxx'), TO_TIMESTAMP('2020-11-22 22:50:23.518000', 'SYYYY-MM-DD HH24:MI:SS:FF6'), '标准地图')
INSERT INTO "B_FILE" VALUES ('409f586f-f086-48a8-a367-4d42fba26890', '谢岗.jpg', 'image/jpeg', '562335', NULL, HEXTORAW('xxxxxx'), TO_TIMESTAMP('2020-11-22 22:51:08.539000', 'SYYYY-MM-DD HH24:MI:SS:FF6'), '标准地图')
INSERT INTO "B_FILE" VALUES ('cf923739-6938-448f-af06-bc8d70678dac', '桥头.jpg', 'image/jpeg', '519045', NULL, HEXTORAW('xxxxxx'), TO_TIMESTAMP('2020-11-22 22:51:49.255000', 'SYYYY-MM-DD HH24:MI:SS:FF6'), '标准地图')

 

b_file表结构

-- Create table
create table B_FILE
(
  file_id         VARCHAR2(64) not null,
  file_name       VARCHAR2(64),
  file_type       VARCHAR2(100),
  file_size       VARCHAR2(16),
  file_small      BLOB,
  file_tx         BLOB,
  file_createtime TIMESTAMP(6),
  file_remark     VARCHAR2(512)
)
tablespace DATA
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
-- Create/Recreate primary, unique and foreign key constraints 
alter table B_FILE
  add primary key (FILE_ID)
  using index 
  tablespace DATA
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );

 

说明

1、此示例中b_file表存在两个blob字段,且所有记录的file_small字段均为null,如果处理的表不止一个blob字段,需根据实际情况调整代码逻辑

2、对于此代码造成的数据丢失本人概不负责

 

参考链接:

https://blog.csdn.net/rexueqingchun/article/details/78150877

https://blog.csdn.net/qq_34514384/article/details/51134416

 

posted @ 2021-10-26 10:11  Nihaorz  阅读(1203)  评论(0编辑  收藏  举报