如何发送一个像我可以使用PrintWriter发送字符串的对象

时间:2014-06-20 14:38:21

标签: java client-server draw send

您好我正在处理简单的客户端服务器应用程序,其中客户端可以使用文本绘制图片和聊天,我在按下按钮时发送文本,并且我想以相同的方式发送名为ColorPointSize的对象List列表中的点,颜色和点的大小,然后在面板上绘制。我可以像通过PrintWriter发送字符串一样简单的方式,或者我将它们转换为String(),然后以某种方式将其转换回ColorPointSize或使用序列化,但我真的不知道如何做到这一点我&# 39;对于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();
    }

}

1 个答案:

答案 0 :(得分:0)

这一切归结为序列化和反序列化数据,你可能已经创建了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类中放置一些基本上不是Serializable的东西,例如Socket对象,那么这将不起作用。

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

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

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()”方法的某些组合。