Java 如何使用PrintWriter发送类似于发送字符串的对象

Java 如何使用PrintWriter发送类似于发送字符串的对象,java,client-server,draw,send,Java,Client Server,Draw,Send,嗨,我正在开发一个简单的客户端-服务器应用程序,在这个应用程序中,客户端可以使用文本绘制图片和聊天,我在按下按钮时发送文本,并且我希望以相同的方式发送名为ColorPointSize的对象列表,它指的是点列表、颜色和点的大小,然后在面板上绘制。我可以用像通过PrintWriter发送字符串那样简单的方式来完成吗?或者我应该将它们转换为string(),然后以某种方式将其转换回ColorPointSize或使用序列化,但我真的不知道如何完成,我对Java感到困惑 以下是代码的一些部分: 向服务器发

嗨,我正在开发一个简单的客户端-服务器应用程序,在这个应用程序中,客户端可以使用文本绘制图片和聊天,我在按下按钮时发送文本,并且我希望以相同的方式发送名为ColorPointSize的对象列表,它指的是点列表、颜色和点的大小,然后在面板上绘制。我可以用像通过PrintWriter发送字符串那样简单的方式来完成吗?或者我应该将它们转换为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类型的对象列表)

ColorPointSize类(以防万一)


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

java.io
实际上提供了一组整洁的类:
java.io.ObjectInputStream
java.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类中放入一些基本上不可序列化的内容,例如套接字对象,那么这将不起作用

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

一般来说,编写原始对象可能很方便,但并不总是最有效的方法。类似地,有时您的类无法直接序列化,您需要更好的控制。一种常见的模式是简单地向类中添加方法以进行序列化和反序列化,如下所示:

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);
  }
}
然后,您可以使用
newdataoutputstream(newfileoutputstream(“foo.dat”))
而不是
newobjectoutputstream
,同样,也可以在输入端使用
newdatainputstream
。一般来说,您需要将每个通信通道的输入端和输出端视为一对,然后您可以真正选择任何策略,以某种方式将数据保存到流中,以便在另一端轻松恢复。在上面的示例中,如果您希望序列化格式是人类可读的,那么您可以同样轻松地使用一些“toString()”方法的组合

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);
  }
}