如何发送一个对象,比如我可以使用printwwriter发送字符串



嗨,我正在研究简单的客户端服务器应用程序,其中客户端可以使用文本绘制图片和聊天,我在按下按钮时发送文本,我想以同样的方式发送名为ColorPointSize的对象列表,该列表指的是点,颜色和点的大小,然后在面板上绘制。我能做到这一点,在通过printwwriter发送字符串的简单方式,或者我将它们转换为string(),然后以某种方式转换回ColorPointSize或使用序列化,但我真的不知道如何做到这一点,我是Java的初学者,我感到困惑。

下面是部分代码:发送消息到服务器

private void sendButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           
    // TODO add your handling code here:
    String nothing = "";
    if ((inputTextArea.getText()).equals(nothing)) {
        inputTextArea.setText("");
        inputTextArea.requestFocus();
    } else {
        try {
           writer.println(username + ":" + inputTextArea.getText() + ":" + "Chat");
           //  here i want to send also an object of type shall i do it via changing toString() and then somehow converting it or what ???
           Date now = new Date();
           String temp=inputTextArea.getText();
           s_archiwum="n"+s_archiwum+"n"+now+" "+temp+"n";
           writer.flush(); // flushes the buffer
        } catch (Exception ex) {
            chatTextArea.append("Message was not sent. n");
        }
        inputTextArea.setText("");
        inputTextArea.requestFocus();
    }
    inputTextArea.setText("");
    inputTextArea.requestFocus();
}          

将连接用户的名称添加到在线用户列表中我想以类似的方式添加ColorPointSize。

public void userAdd(String data) {
    String message, add = ": :Connect", done = "Server: :Done", name = data;
    outputPane.append("Before " + name + " added. n");
    onlineUsers.add(name);
    outputPane.append("After " + name + " added. n");
    String[] tempList = new String[(onlineUsers.size())];
    onlineUsers.toArray(tempList);
    for (String token : tempList) {
        message = (token + add);
        tellEveryone(message);
    }
    tellEveryone(done);
}

绘制方法:(cps是一个类型为ColorPointSize的对象列表)

private void drawRoundRectangles(Graphics2D g2d) {
    int x, y, x2, y2;
    synchronized (cps) {
        for (ColorPointSize p : cps) {
            g2d.setColor(p.color);
            x = (int) p.getX();
            y = (int) p.getY();
            x2 = (int) p.getX() - 1;
            y2 = (int) p.getY() - 1;
            g2d.drawLine(x, y, x2, y2);
            g2d.fillRoundRect(x, y, p.size, p.size, p.size, p.size);
            g2d.drawLine(x, y, x2, y2); // connectin' points wit' line
        }
    }
}

ColorPointSize类(以防万一)

package paintalk;
import java.awt.Color;
import java.awt.Point;
public class ColorPointSize {
    public Color color;
    public Point point;
    public int size;
    public ColorPointSize(Color c, Point p, int s) {
        this.color = c;
        this.point = p;
        this.size = s;
    }
    ColorPointSize(Point p) {
        this.point = p;
    }
    double getX() {
        return point.getX();
    }
    double getY() {
        return point.getY();
    }
}

这一切都归结为序列化和反序列化数据,您可能已经创建了PrintWriter来写入某种OutputStream(甚至可能是System.out,这只是一个方便的OutputStream)。

java.io实际上提供了一组简洁的类:java.io.ObjectInputStreamjava.io.ObjectOutputStream。你可以将它们作为一对来发送任意Java对象,只要它们在它们的类定义中添加"implements Serializable"——实现"Serializable"实际上并没有添加任何方法,它只是用作Java的一个特殊标记,允许将对象简化为低级字节,只要对象中的每个项也定义为"implements Serializable"就可以工作。试试下面的例子,将其命名为Test.java并运行"java Test";我用"implements Serializable"修改了ColorPointSize类,但它在其他方面没有变化:

import java.io.*;
import java.awt.Color;
import java.awt.Point;
class ColorPointSize implements Serializable {
  public Color color;
  public Point point;
  public int size;
  public ColorPointSize(Color c, Point p, int s){
    this.color=c;
    this.point=p;
    this.size=s;
  }
  ColorPointSize(Point p){
    this.point=p;
  }
  double getX(){
    return point.getX();
  }
  double getY(){
    return point.getY();
  }
}
public class Test {
  public static void main(String[] args) throws Exception {
    ColorPointSize foo = new ColorPointSize(
        new Color(123, 222, 111), new Point(42, 24), 50);
    System.out.println(foo.color);
    System.out.println(foo.point);
    System.out.println(foo.size);
    ObjectOutputStream fout = new ObjectOutputStream(
        new FileOutputStream(new File("foo.dat")));
    fout.writeUnshared(foo);
    fout.close();
    ObjectInputStream fin = new ObjectInputStream(
        new FileInputStream(new File("foo.dat")));
    ColorPointSize bar = (ColorPointSize) fin.readUnshared();
    fin.close();
    System.out.println(bar.color);
    System.out.println(bar.point);
    System.out.println(bar.size);
  }
}

如果运行这个示例,您将看到这个示例成功地将ColorPointSize实例的所有内部内容写入到一个文件中,然后将其读入,恢复其所有设置。请注意,如果你试图在ColorPointSize类中放入一些基本上不可序列化的东西,例如Socket对象,那么这将不起作用。

现在,不是像示例中那样将ObjectOutputStream包装在FileOutputStream周围,而是可以将其包装在任何其他类型的OutputStream中,例如由网络套接字提供的,如果编写客户机/服务器应用程序,您可能会使用它。

一般来说,编写原始对象可能很方便,但它可能并不总是最有效的方法。同样,有时您的类不能直接序列化,而您需要更好的控制。一种常见的模式是简单地向类中添加用于序列化和反序列化的方法,如下所示:
class ColorPointSize {
  public Color color;
  public Point point;
  public int size;
  public void deserializeFrom(DataInputStream in) {
    this.color = new Color(in.readInt(), in.readInt(), in.readInt());
    this.point = new Point(in.readInt(), in.readInt());
    this.size = in.readInt();
  }
  public void serializeTo(DataOutputStream out) {
    out.writeInt(color.getRed());
    out.writeInt(color.getGreen());
    out.writeInt(color.getBlue());
    out.writeInt(point.getX());
    out.writeInt(point.getY());
    out.writeInt(size);
  }
}

或者更有效地:

class ColorPointSize {
  public Color color;
  public Point point;
  public int size;
  public void deserializeFrom(DataInputStream in) {
    this.color = new Color(in.readInt());
    this.point = new Point(in.readInt(), in.readInt());
    this.size = in.readInt();
  }
  public void serializeTo(DataOutputStream out) {
    out.writeInt(color.getRGB());
    out.writeInt(point.getX());
    out.writeInt(point.getY());
    out.writeInt(size);
  }
}

然后,您可以使用new DataOutputStream(new FileOutputStream("foo.dat"))而不是new ObjectOutputStream,同样地,在输入端使用new DataInputStream。一般来说,您需要将每个通信通道的输入端和输出端都视为一对,然后您可以选择任何策略,以某种方式将数据保存到流中,以便在另一端轻松恢复。在上面的例子中,如果您希望您的序列化格式是人类可读的,您可以很容易地使用一些"toString()"方法的组合。

最新更新