【问题标题】:java, writing data size with DataOutputStreamjava,用 DataOutputStream 写入数据大小
【发布时间】:2016-10-17 18:58:51
【问题描述】:

我有一系列通过 DataOutputStream 将数据写入文件的对象。

随着我的应用程序文件格式的发展,我将向其中添加更多数据对象,这些数据对象应该能够被“旧”版本的应用程序读取。

为了能够做到这一点,我需要在对象数据前面加上一个大小值,指示当前对象将占用的字节数。

但是,由于这些数据可以是可变大小,特别是在处理字符串时,我无法事先知道大小。

有没有办法“预写”到字节缓冲区,就好像它是一个 DataOutputStream(特别是方法 - writeByte、writeShort、writeInt、writeUTF),这将使我能够获得在将数据写入 DataOutputStream 之前返回数据的字节长度?这样做可以让我跳过旧版本的应用程序确实理解的新数据对象。

【问题讨论】:

  • 你是自己序列化对象,还是使用java内置的序列化?
  • 您需要以二进制格式存储数据,还是可以将数据对象编组为文本,例如JSON 或 YAML 与 Jackson 之类的库?使用库进行繁重的工作时,反序列化也应该变得非常简单。
  • 如果你自己序列化它,我使用this 技术来序列化字符串,但你也可以使用空终止
  • 我自己在序列化对象。我没有使用任何形式的文本序列化。因此这是一种二进制格式,因此需要能够确定数据大小。

标签: java outputstream dataoutputstream


【解决方案1】:

由于各种原因,常规 Java 序列化并不是那么好。最重要的一个是它非常脆弱,并且往往不是“面向未来的”。如果可能的话,我建议您使用不同的序列化格式,特别是如果您特别提到您计划将字段添加到您序列化的类中。

ProtobufJSON 等格式的 Java 库具有良好的 API 和良好的向前/向后兼容性功能。在大多数情况下,将数据序列化为更方便的格式要比解决现有格式的问题简单得多。

【讨论】:

    【解决方案2】:

    如您所见here,您可以这样使用java.lang.instrument.Instrumentation

    import java.lang.instrument.Instrumentation;
    
    public class ObjectSizeFetcher {
        private static Instrumentation instrumentation;
    
        public static void premain(String args, Instrumentation inst) {
            instrumentation = inst;
        }
    
        public static long getObjectSize(Object o) {
            return instrumentation.getObjectSize(o);
        }
    }
    

    然后计算对象的大小(以字节为单位):

    public static void main(String [] args) {
       Object myObject = ...;
            System.out.println(ObjectSizeFetcher.getObjectSize(myObject));
        }
    

    【讨论】:

    • 看起来很有趣。但是,我要查找的不是对象的大小,而是要写出的二进制数据的大小或长度。
    猜你喜欢
    • 1970-01-01
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    相关资源
    最近更新 更多