【问题标题】:writeUTF(String s) vs writeObject(String s)writeUTF(String s) 与 writeObject(String s)
【发布时间】:2021-03-12 17:05:31
【问题描述】:

在我正在为大学工作的这个 Java 项目中,我目前正在使用成功通过网络发送字符串的情况

streamOut = ObjectOutputStream
streamIn = ObjectInputStream

streamOut.writeUTF(msgs.peek());

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

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

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

我想同时发送 Strings 和另一个 Object 类型,通过网络将其称为 gameWorld(此时不关心效率).. 但是当我这样做时

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

Object in = streamIn.readObject(); 
if(in instanceof String) String inS = (String) in;

当我发送字符串时它没有收到任何东西......我的朋友正在做同一个项目,他只传递了一种类型的对象,这个对象的一个​​子类本质上是一个字符串和他的版本工作正常,但他在线程运行循环的每次迭代中都会创建一个新流。

我是否需要对流做一些事情来接收除了 Object 之外没有共同祖先的不同对象,我是否需要在运行循环的每次迭代中创建一个新流,或者是否还有其他完全我失踪了,我提供的信息不足以判断出什么问题?

【问题讨论】:

  • 你的意思是Object in = streamIn.readObject(); 在这行后面是空的吗?

标签: java networking serialization dataoutputstream


【解决方案1】:

将字符串作为原始数据或作为对象写入流中存在显着差异。 writeObject 写入的 String 实例最初作为 String 写入流中。未来的 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 i r s t t S e c o n d t T h i r d

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 i r s t S 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)

【讨论】:

  • 轰隆隆,成功了。谢谢,我不知道参考的东西,这就是吸引我的原因,也是为什么我的朋友版本每次都会创建一个新流。
  • 这两个十六进制转储之间没有区别。您已经发布了两次相同的内容。第一个与给出的 ASCII 渲染不符。
【解决方案2】:

如果你想用 readObject() 读取字符串,你必须用 writeObject() 来写。

【讨论】:

    【解决方案3】:

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

    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()),这可能会产生巨大的差异。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-24
      • 1970-01-01
      • 2016-06-25
      • 2015-06-10
      相关资源
      最近更新 更多