7

我有一个 BitSet 并想将其写入文件 - 我遇到了一个使用 writeObject 方法使用 ObjectOutputStream 的解决方案。

我查看了 java API 中的 ObjectOutputStream,发现您可以编写其他东西(字节、整数、短等)

我试图检查类,所以我尝试使用以下代码将一个字节写入文件,但结果给了我一个 7 字节而不是 1 字节的文件

我的问题是文件中的前 6 个字节是什么?他们为什么在那里?

我的问题与 BitSet 有关,因为我不想开始将大量数据写入文件并意识到我在文件中插入了随机字节而不知道它们是什么。

这是代码:

    byte[] bt = new byte[]{'A'};
    File outFile = new File("testOut.txt");
    FileOutputStream fos = new FileOutputStream(outFile);
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.write(bt);
    oos.close();

谢谢你的帮助

阿夫纳

4

4 回答 4

2

其他字节将是类型信息。

基本上 ObjectOutputStream 是一个用于将 Serializable 对象写入某个目的地(通常是文件)的类。如果您考虑 InputObjectStream,它会更有意义。它有一个 readObject() 方法。Java如何知道要实例化什么对象?简单:里面有类型信息。

于 2009-09-04T09:35:17.050 回答
1

您可以将任何对象写入ObjectOutputStream,因此流包含有关写入类型的信息以及重构对象所需的数据。

如果您知道流将始终包含一个 BitSet,请不要使用ObjectOutputStream- 并且如果空间很重要,则将 转换BitSet为一组字节,其中每个位对应于 中的一个位BitSet,然后将其直接写入底层流(例如FileOutputStream您的示例中的 a )。

于 2009-09-04T09:34:36.350 回答
0

与许多其他格式一样,序列化格式包括带有幻数和版本信息的标头。当你使用DataOutput/OutputStream方法时ObjectOutputStream,放在序列化数据的中间(没有类型信息)。这通常仅在writeObject调用defaultWriteObject或使用putFields.

于 2009-09-04T09:51:12.103 回答
0

如果您只使用 Java 中保存的 BitSet,则序列化工作正常。但是,如果您想跨多个平台共享 bitset,那就有点烦人了。除了 Java 序列化的开销之外,BitSet 以 8 字节为单位存储。如果您的位集很小,这可能会产生过多的开销。

我们编写了这个小类,以便我们可以从 BitSet 中提取字节数组。根据您的用例,它可能比 Java 序列化更适合您。

public class ExportableBitSet extends BitSet {

    private static final long serialVersionUID = 1L;

    public ExportableBitSet() {
        super();
    }

    public ExportableBitSet(int nbits) {
        super(nbits);
    }

    public ExportableBitSet(byte[] bytes) {
        this(bytes == null? 0 : bytes.length*8);        
        for (int i = 0; i < size(); i++) {
            if (isBitOn(i, bytes))
                set(i);
        }
    }

    public byte[] toByteArray()  {

        if (size() == 0)
            return new byte[0];

        // Find highest bit
        int hiBit = -1;
        for (int i = 0; i < size(); i++)  {
            if (get(i))
                hiBit = i;
        }

        int n = (hiBit + 8) / 8;
        byte[] bytes = new byte[n];
        if (n == 0)
            return bytes;

        Arrays.fill(bytes, (byte)0);
        for (int i=0; i<n*8; i++) {
            if (get(i)) 
                setBit(i, bytes);
        }

        return bytes;
    }

    protected static int BIT_MASK[] = 
        {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};

    protected static boolean isBitOn(int bit, byte[] bytes) {
        int size = bytes == null ? 0 : bytes.length*8;

        if (bit >= size) 
            return false;

        return (bytes[bit/8] & BIT_MASK[bit%8]) != 0;
    }

    protected static void setBit(int bit, byte[] bytes) {
        int size = bytes == null ? 0 : bytes.length*8;

        if (bit >= size) 
            throw new ArrayIndexOutOfBoundsException("Byte array too small");

        bytes[bit/8] |= BIT_MASK[bit%8];
    }
}
于 2009-09-04T13:31:05.703 回答