嗨,我正在研究简单的客户端服务器应用程序,其中客户端可以使用文本绘制图片和聊天,我在按下按钮时发送文本,我想以同样的方式发送名为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.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类中放入一些基本上不可序列化的东西,例如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()"方法的组合。