writeUTF(String s)vs writeObject(String s)

时间:2013-10-09 10:37:16

标签: java networking serialization dataoutputstream

在我正在为大学工作的这个Java项目中,我遇到的情况是我正在使用

成功通过网络发送字符串
streamOut = ObjectOutputStream
streamIn = ObjectInputStream

streamOut.writeUTF(msgs.peek());

其中msgs是一个链接的阻塞队列,用

接收它
String in = streamIn.readUTF();

但是,我想使用ObjectInputStream和ObjectOutputStream。我已经在构造函数中初始化它们,并在构造它之后刷新ObjectOutputStream,我读到了你必须要做的地方。

我想发送两个字符串和另一个Object类型,通过网络称它为gameWorld(此时不关心效率)..但是当我这样做时

streamOut.writeObject("mad cuz i'm bad");

Object in = streamIn.readObject(); 
if(in instanceof String) String inS = (String) in;
当我发送字符串时,它没有选择任何东西......我的朋友正在处理同一个项目,他只传递一种类型的对象,这个对象的一个​​子类本质上是一个字符串和他的版本工作正常,但他在他的线程的运行循环的每次迭代中都创建了一个新流。

我是否需要对流做一些事情以接收不具有除Object之外的共同祖先的不同对象,我是否需要在运行循环的每次迭代中创建一个新流,或者是否只有完全相同的东西我失踪了,我提供的信息不足以说明错了什么?

3 个答案:

答案 0 :(得分:4)

将String作为原始数据或Object写入流中之间存在显着差异。 writeObject编写的String实例最初以String形式写入流中。 Future writeObject()将对字符串的写入引用调用到流中。

例如

    ByteArrayOutputStream baos1=new ByteArrayOutputStream();
    oos1=new ObjectOutputStream(baos1);
    baos2=new ByteArrayOutputStream();
    ObjectOutputStream oos2=new ObjectOutputStream(baos2);
    String testString="First";
    oos1.writeObject(testString);
    oos2.writeUTF(testString);
    testString="Second";
    oos1.writeObject(testString);
    oos2.writeUTF(testString);
    testString="Third";
    oos1.writeObject(testString);
    oos2.writeUTF(testString);
    oos1.flush();
    oos2.flush();
    byte[] byteArray1=baos1.toByteArray();
    byte[] byteArray2=baos2.toByteArray();

转储最后两个数组,你会得到如下结果:
writeObject 即byteArray1
二进制:-84 -19 0 5 116 0 5 70 105 114 115 116 116 0 6 83 101 99 111 110 100 116 0 5 84 104 105 114 100 ASCII:-T - t F t

writeUTF 即byteArray2
二进制:-84 -19 0 5 119 22 0 5 70 105 114 115 116 0 6 83 101 99 111 110 100 0 5 84 104 105 114 100
ASCII:-T - w F r r s t e c o n d T h i r d

结论:如果writeObject需要流式传输额外的数据(此处为 t ),而在writeUTF的情况下,只有要传输的字符串数据。

更多信息:http://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html#writeUTF(java.lang.String)

答案 1 :(得分:0)

如果要使用readObject()读取字符串,则必须使用writeObject()编写它。

答案 2 :(得分:0)

最重要的区别是,如果你用 writeUTF() 写字符串,那么整个字符串将始终作为 UTF 编码字符写入流。但是,如果您使用 writeObject(),则 String 的 Object 实例将写入流。所以如果你用writeObject()写了同一个实例的多个Strings,那么readObject()返回的对应Strings也会保证是同一个Object实例,而当你用readUTF()读取它们的时候,它们将不是是同一个对象实例:

ByteArrayOutputStream bytes1 = new ByteArrayOutputStream();
ObjectOutputStream out1 = new ObjectOutputStream(bytes1);
ByteArrayOutputStream bytes2 = new ByteArrayOutputStream();
ObjectOutputStream out2 = new ObjectOutputStream(bytes2);

String writeString = "test";
out1.writeObject(writeString);
out1.writeObject(writeString);

out2.writeUTF(writeString);
out2.writeUTF(writeString);

out1.flush();
out2.flush();

ObjectInputStream in1 = new ObjectInputStream(new ByteArrayInputStream(bytes1.toByteArray()));
ObjectInputStream in2 = new ObjectInputStream(new ByteArrayInputStream(bytes2.toByteArray()));

String readString1 = (String) in1.readObject();
String readString2 = (String) in1.readObject();

System.out.println(readString1 == readString2);

readString1 = (String) in2.readUTF();
readString2 = (String) in2.readUTF();

System.out.println(readString1 == readString2);

打印:

true
false

这也会导致非常不同的流:使用 writeUTF() 我们得到一个长度为 18 的 byte[],其中包含两次 UTF 字符“test”。使用 writeObject() 我们得到一个长度为 16 的 byte[] ,它只包含一次 UTF 字符“test”,后跟一个表示字符串引用 ID 的整数。所以 writeObject() 通常会导致文件变小。如果将同一实例的大量字符串写入流(例如,通过调用 String.intern()),这会产生巨大的差异。