2009-09-04 19 views
6

Tengo un BitSet y quiero escribirlo en un archivo. Encontré una solución para usar un ObjectOutputStream usando el método writeObject.escribiendo un BitSet en un archivo en java

Miré el ObjectOutputStream en la API de Java y vieron que se puede escribir otras cosas (byte, int, short, etc)

he tratado de revisar la clase así que traté de escribir un byte en un archivo utilizando el siguiente código pero el resultado me da un archivo con 7 bytes en lugar de 1 byte

mi pregunta es ¿cuáles son los primeros 6 bytes en el archivo? ¿Por qué están ellos ahí?

mi pregunta es relevante para un BitSet porque no quiero comenzar a escribir muchos datos en un archivo y me doy cuenta de que tengo bytes aleatorios insertados en el archivo sin saber cuáles son.

Aquí está el código:

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(); 

gracias por cualquier ayuda

Avner

Respuesta

2

Los otros bytes serán información de tipo.

Básicamente ObjectOutputStream es una clase utilizada para escribir objetos serializables en algún destino (normalmente un archivo). Tiene más sentido si piensas en InputObjectStream. Tiene un método readObject() en él. ¿Cómo sabe Java qué objeto instanciar? Fácil: hay información tipo allí.

+0

así que si te entiendo correctamente, cada vez que escribo algo con ObjectOutputStream, tengo una sobrecarga importante por cada escritura. por ejemplo, si escribo un int, un short, un byte y luego una cadena obtengo 4 conjuntos de datos adicionales para cada artículo que escribo? – Avner

+2

No. Solo el método writeObject() agrega el encabezado de tipo. El método writeUTF() agrega un prefijo de longitud de 2 bytes. Los métodos primitivos writeXX() no agregan ninguna sobrecarga. Lee el documento API para más detalles. –

+1

También tenga en cuenta que la información de tipo es por Objeto. Para un objeto que consiste básicamente en una matriz primitiva (como BitSet), la sobrecarga es constante, sin importar qué tan grande sea la matriz. –

1

Usted podría estar escribiendo ningún objeto a un ObjectOutputStream, por lo que la corriente contiene información acerca de los tipos escritos como así como los datos necesarios para reconstituir el objeto.

si se sabe que la corriente siempre contendrá una BitSet, no utilice un ObjectOutputStream - y si el espacio es un bien escaso, a continuación, convertir el BitSet a un conjunto de bytes que cada bit corresponde a un bit en la BitSet, luego, escribe eso directamente en la secuencia subyacente (por ejemplo, FileOutputStream como en tu ejemplo).

+0

Desafortunadamente, BitSet no tiene un método incorporado para convertirlo en una matriz de bytes. – finnw

+0

Existe el método: 'toByteArray()' – clankill3r

+0

@ clankill3r: Sí, junto con 'toLongArray()', pero solo desde Java 7. – charlie

0

El formato de serialización, como muchos otros, incluye un encabezado con número mágico e información de versión. Cuando utiliza DataOutput/OutputStream los métodos en ObjectOutputStream se colocan en el medio de los datos serializados (sin información de tipo). Esto normalmente solo se realiza en implementaciones writeObject después de una llamada a defaultWriteObject o uso de putFields.

0

Si solo usa el BitSet guardado en Java, la serialización funciona bien. Sin embargo, es un poco molesto si quieres compartir el conjunto de bits a través de múltiples plataformas. Además de la sobrecarga de la serialización de Java, el BitSet se almacena en unidades de 8 bytes. Esto puede generar demasiada sobrecarga si su conjunto de bits es pequeño.

Escribimos esta pequeña clase para que podamos extar las matrices de bytes de BitSet. Según su caso de uso, podría funcionar mejor que la serialización de Java para usted.

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]; 
    } 
} 
Cuestiones relacionadas