【问题标题】:How can I retrieve image from MySQL to Java Swing?如何将图像从 MySQL 检索到 Java Swing?
【发布时间】:2018-04-10 02:39:59
【问题描述】:

我想从 MySQL 中检索图像并使用 Java Swing 将其加载到 JLabel

但我无法完成这项工作。

下面是我的代码和我得到的错误:

try {
    Class.forName("com.mysql.jdbc.Driver");  // MySQL database connection
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/image_db", "root", "root");
    PreparedStatement pst = conn.prepareStatement("Select * from image_tbl where id='"+jTextField1.getText()+"'");
    ResultSet rs = pst.executeQuery();

    byte b[] = null;
    while(rs.next())
     {
       b= rs.getBytes(2);
     }

     jLabel1.setIcon(new ImageIcon (Toolkit.getDefaultToolkit().createImage(b)));
} catch (Exception e) {
    JOptionPane.showMessageDialog(null, "Wrong Data Detected! Please provide correct data");
}    

发生异常:

    sun.awt.image.ImageFormatException: JPEG datastream contains no image
        at sun.awt.image.JPEGImageDecoder.readImage(Native Method)
        at sun.awt.image.JPEGImageDecoder.produceImage(JPEGImageDecoder.java:141)
        at sun.awt.image.InputStreamImageSource.doFetch(InputStreamImageSource.java:269)
        at sun.awt.image.ImageFetcher.fetchloop(ImageFetcher.java:205)
        at sun.awt.image.ImageFetcher.run(ImageFetcher.java:169)
    Premature end of JPEG file

【问题讨论】:

  • 您正在选择表格中的每一列。您应该只选择具有图像字节的列。
  • 首先,如前所述,您读取所有结果只是为了加载最后一张图片;其次,我会验证读取的字节数与写入的字节数相同,但是由于我们不知道图像是如何写入的,所以我们不知道使用这种方法是否是最好的主意;第三,我会使用ImageIO 而不是createImage,只是因为它不涉及任何类型的线程
  • 您可能会考虑只存储某种图像标识符,然后可用于从本地或远程源(如 Web 服务)查找和加载图像
  • 当我必须做这样的事情时,我使用 blob 数据类型和 JDBC 提供的 Input/OutputStream 接口来处理数据类型。如果图像存储在数据库中,最好考虑它们可能的压缩方式(java 提供了一个方便的 gzip 接口)。

标签: java mysql image swing


【解决方案1】:

这是一个在 mysql blob 中序列化图像(图标)的简单示例。

创建表t1(id整型主键auto_increment,img longblob不为空);

public class Database {
    public Database() {
    }

    private Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "toor");
    }

    public boolean storeIcon(Icon icon) throws SQLException, IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try(ObjectOutputStream os = new ObjectOutputStream(baos)) {
            os.writeObject(icon);
        }

        try(Connection connection = getConnection()) {
            String query = "insert into t1 (img) values (?)";

            try(PreparedStatement statement = connection.prepareStatement(query)) {
                statement.setBlob(1, new ByteArrayInputStream(baos.toByteArray()));
                return statement.executeUpdate() > 0;
            }
        }
    }

    public Icon loadIcon(long id) throws SQLException, IOException, ClassNotFoundException {
        try(Connection connection = getConnection()) {
            String query = "select img from t1 where id = ?";

            try(PreparedStatement statement = connection.prepareStatement(query)) {
                statement.setLong(1, id);

                try(ResultSet rs = statement.executeQuery()) {
                    if(rs.next()) {
                        Blob blob = rs.getBlob("img");

                        try(ObjectInputStream is = new ObjectInputStream(blob.getBinaryStream())) {
                            return (Icon) is.readObject();
                        }
                    }

                    return null;
                }
            }
        }
    }
}

这是一个测试应用程序。从数据库中读取图像是使用等于 1 的固定图像 ID 执行的,仅用于演示。在实际实现中,最好压缩数据以节省空间。当然,记录的图像(对象)的提取应该限制在绝对最小值。

public class MainFrame extends JFrame {

    private JLabel imageLabel = new JLabel();

    private JButton loadImageFromFileButton = new JButton("Load image from file");
    private JButton storeImageIntoDBButton = new JButton("Store image into DB");
    private JButton loadImageFromDBButton = new JButton("Load image from DB");

    public MainFrame() throws HeadlessException {
        super("JDBC Test");
        createGUI();
    }

    private void createGUI() {
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setLayout(new BorderLayout(5, 20));

        imageLabel.setPreferredSize(new Dimension(200, 200));
        imageLabel.setHorizontalAlignment(JLabel.CENTER);
        imageLabel.setVerticalAlignment(JLabel.CENTER);

        loadImageFromFileButton.addActionListener(this::loadImageFromFile);
        loadImageFromDBButton.addActionListener(this::loadImageFromDB);
        storeImageIntoDBButton.addActionListener(this::storeImageIntoDB);

        JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
        buttonsPanel.add(loadImageFromFileButton);
        buttonsPanel.add(Box.createHorizontalStrut(25));
        buttonsPanel.add(loadImageFromDBButton);
        buttonsPanel.add(Box.createHorizontalStrut(5));
        buttonsPanel.add(storeImageIntoDBButton);

        add(imageLabel, BorderLayout.CENTER);
        add(buttonsPanel, BorderLayout.PAGE_END);

        pack();
        setLocationRelativeTo(null);
    }

    private void loadImageFromFile(ActionEvent event) {
        JFileChooser chooser = new JFileChooser();
        if(chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            ImageIcon imageIcon = new ImageIcon(chooser.getSelectedFile().getAbsolutePath());
            imageLabel.setIcon(imageIcon);
        }
    }

    private void storeImageIntoDB(ActionEvent event) {
        try {
            Database db = new Database();
            db.storeIcon(imageLabel.getIcon());
        }
        catch (SQLException | IOException e) {
            e.printStackTrace();
        }
    }

    private void loadImageFromDB(ActionEvent event) {
        try {
            Database db = new Database();
            Icon icon = db.loadIcon(1L);
            imageLabel.setIcon(icon);
        }
        catch (SQLException | IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true));
    }
}

【讨论】:

  • 出现异常:未找到驱动程序应在程序中添加驱动程序的位置
  • 在app的classpath中,必须添加mysql驱动jar文件。如果您使用 4.2 之前的 JDBC 版本,则必须使用 Class.forName("com.mysql.jdbc.Driver"); 加载它。所有这些都是您在项目中完成的,因此您应该不会对这段代码有任何问题。
猜你喜欢
  • 2022-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
  • 2017-09-28
  • 2013-01-08
  • 2015-05-31
相关资源
最近更新 更多