如何序列化ImageIcon对象?

How to Serialize ImageIcon Object?

我正在尝试构建一个客户端-服务器程序,其中服务器将图像发送到客户端,客户端在 JFrame 中显示接收到的图像。我正在将服务器端的图像转换为 ImageIcon 对象并通过 ObjecOutputStream 将其发送到客户端。但它失败了,并在服务器端给我 加载图像内容失败错误 ,它发生在调用 ObjectOutputStream.writeObject() 方法时。

服务器端代码

import java.io.*;
import java.net.*;
import javax.swing.*;

public class ImageServer{

  private static ServerSocket serverSocket;
  private static final int PORT = 1234;

  public static void main(String[] args){

       System.out.println("Opening port…\n");
       try{
         serverSocket = new ServerSocket(PORT);
       }
       catch(IOException ioEx){
         System.out.println("Unable to attach to port!");
         System.exit(1);
       }
       while(true){
             try{
               Socket connection = serverSocket.accept();

               ObjectOutputStream outStream =new ObjectOutputStream(
                                              connection.getOutputStream());
               ImageIcon icon=new ImageIcon("//Give image path//");
               System.out.println(icon.getImageLoadStatus());// To check if image is loded correctly or not.

               outStream.writeObject(icon);

               outStream.flush();
             }
            catch(IOException ioEx){
                ioEx.printStackTrace();
            }
      }
 }
}

只给出图片文件的路径,以供测试。

客户端代码

import java.io.*;
import java.net.*;
import java.awt.*; 
import java.awt.event.*;
import javax.swing.*;

public class ImageClient extends JFrame{
    private InetAddress host;
    private final int PORT = 1234;
    private ImageIcon image;

    public static void main(String[] args){

         ImageClient pictureFrame = new ImageClient();
         pictureFrame.setSize(340,315);
         pictureFrame.setVisible(true);
         pictureFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);  
    }

   public ImageClient(){
        try{
           host = InetAddress.getLocalHost();
        }
        catch(UnknownHostException uhEx){

            System.out.println("Host ID not found!");
            System.exit(1);
        }

        try{
            Socket connection = new Socket(host,PORT);

            ObjectInputStream inStream =new ObjectInputStream(
                                           connection.getInputStream());

            image = (ImageIcon)inStream.readObject();

            connection.close();
        }
        catch(IOException ioEx){
              ioEx.printStackTrace();
        }
        catch(ClassNotFoundException cnfEx){
              cnfEx.printStackTrace();
        }

        repaint();
  }

  public void paint(Graphics g){
       image.paintIcon(this,g,0,0);
   }
}

服务器端产生错误

java.io.IOException: failed to load image contents
     at javax.swing.ImageIcon.writeObject(Unknown Source)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
     at java.lang.reflect.Method.invoke(Unknown Source)
     at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
     at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
     at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
     at java.io.ObjectOutputStream.writeObject0(Unknown Source)
     at java.io.ObjectOutputStream.writeObject(Unknown Source)
     at ImageServer.main(ImageServer.java:27)

这是以下书中的代码摘录: http://www.springer.com/us/book/9781447152538

好的,所以我使用 Netbeans 创建了一个项目。我在名为 images.

的包中放置了一张图片(名为 29bd6417998561.5635a605ad357.png

我创建了 Server class...

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

public class Server {

    private static final int PORT = 9999;

    public static void main(String[] args) {

        System.out.println("Opening port…\n");
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            while (true) {
                ;
                try {
                    System.out.println("Waiting for connection");
                    Socket connection = serverSocket.accept();

                    System.out.println("Read image...");
                    ImageIcon icon = new ImageIcon(ImageIO.read(Server.class.getResource("/images/29bd6417998561.5635a605ad357.png")));

                    System.out.println("Read image...");
                    try (ObjectOutputStream outStream = new ObjectOutputStream(connection.getOutputStream())) {
                        System.out.println("Write image");
                        outStream.writeObject(icon);
                    }
                } catch (IOException ioEx) {
                    ioEx.printStackTrace();
                }
            }
        } catch (IOException ioEx) {
            System.out.println("Unable to attach to port!");
            System.exit(1);
        }
    }
}

并创建了 Client class...

import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Client {

    private InetAddress host;
    private final int PORT = 9999;
    private ImageIcon image;
    private JLabel label;

    public static void main(String[] args) {

        Client pictureFrame = new Client();
    }

    public Client() {
        try {
            host = InetAddress.getLocalHost();
        } catch (UnknownHostException uhEx) {

            System.out.println("Host ID not found!");
            System.exit(1);
        }

        JFrame frame = new JFrame();
        label = new JLabel();
        frame.add(label);

        System.out.println("Connect to server");
        try (Socket connection = new Socket(host, PORT)) {
            try (ObjectInputStream inStream = new ObjectInputStream(connection.getInputStream())) {
                System.out.println("Read image");
                image = (ImageIcon) inStream.readObject();
                label.setIcon(image);
                System.out.println("All done");
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

我启动了 Server 和 运行 以及 Client 并且运行良好...

免责声明...

毫无疑问,其他人会指出此代码的固有问题,但这不是示例的重点。

首先,您永远不应该在事件调度线程中执行阻塞或长 运行 操作(例如连接到服务器 and/or 从中读取图像)。你也不应该从事件调度线程的上下文之外修改 UI(这里有点安全,因为框架没有在屏幕上实现,但仍然不是一个很好的例子)。

在这两种情况下,SwingWorker 之类的东西将有助于解决这些问题。

查看 Work Threads and SwingWorker 了解更多详情