2009-09-04 9 views
6

Mam zestaw bitów i chcę go zapisać do pliku - natknąłem się na rozwiązanie do użycia obiektu ObjectOutputStream przy użyciu metody writeObject.Zapisywanie zestawu bitów do pliku w java

Spojrzałem na ObjectOutputStream w Java API i zobaczyłem, że można napisać innych rzeczy (bajt, int, short itp)

próbowałem sprawdzić klasę więc próbowałem napisać bajt w pliku używając następującego kodu, ale wynik daje mi plik o 7 bajtach zamiast 1 bajcie

moje pytanie brzmi: jakie są pierwsze 6 bajtów w pliku? dlaczego oni tam są?

Moje pytanie dotyczy zestawu bitowego, ponieważ nie chcę zaczynać wpisywania dużej ilości danych do pliku i zdać sobie sprawę, że mam losowe bajty wstawione do pliku, nie wiedząc, jakie one są.

oto kod:

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

dzięki za wszelką pomoc

Avner

Odpowiedz

2

Pozostałe bajty będzie typu informacji.

Zasadniczo ObjectOutputStream jest klasą używaną do zapisu obiektów szeregowalnych do pewnego miejsca docelowego (zwykle plik). Ma to więcej sensu, jeśli myślisz o InputObjectStream. Ma na sobie metodę readObject(). W jaki sposób Java wie, do którego obiektu należy utworzyć instancję? Łatwo: tam jest informacja o typie.

+0

, więc jeśli rozumiem cię poprawnie - za każdym razem, gdy piszę coś przy użyciu ObjectOutputStream, otrzymuję poważny narzut dla każdego zapisu. na przykład, jeśli napiszę int, krótki, bajt, a następnie ciąg otrzymuję 4 zestawy dodatkowych danych dla każdej pozycji, którą piszę? – Avner

+2

Nie. Tylko metoda writeObject() dodaje nagłówek typu. Metoda writeUTF() dodaje przedrostek o długości 2 bajtów. Prymitywne metody writeXX() nie dodają żadnych narzutów. Przeczytaj dokument API, aby uzyskać szczegółowe informacje. –

+1

Należy również pamiętać, że informacja o typie jest dla obiektu. Dla obiektu, który składa się zasadniczo z prymitywnej tablicy (takiej jak BitSet), narzut jest stały, bez względu na to, jak dużą macierz. –

1

Można pisać żadnych przedmiotów na zewnątrz do ObjectOutputStream, więc strumień zawiera informacje o rodzajach pisanych jako oraz dane potrzebne do odtworzenia obiektu.

Jeśli wiesz, że strumień będzie zawsze zawierać BitSet, nie używać ObjectOutputStream - i jeśli przestrzeń jest premii, a następnie przekształcić BitSet do zestawu bajtów, gdzie każdy bit odpowiada bit w BitSet, następnie zapisz to bezpośrednio do podstawowego strumienia (np. FileOutputStream, jak w twoim przykładzie).

+0

Niestety, BitSet nie ma wbudowanej metody konwersji na tablicę bajtów. – finnw

+0

Istnieje metoda: 'toByteArray()' – clankill3r

+0

@ clankill3r: Tak, razem z 'toLongArray()', ale tylko od Javy 7. – charlie

0

format serializacji, podobnie jak wiele innych, zawiera nagłówek z magicznej liczby i informacje o wersji. Podczas korzystania z metod DataOutput/OutputStream metody ObjectOutputStream są umieszczane w środku zserializowanych danych (bez informacji o typie). Zwykle robi się to tylko w implementacjach writeObject po wywołaniu defaultWriteObject lub użyciu putFields.

0

Jeśli tylko skorzystać z zapisanego BitSet w Javie, serializacji działa dobrze. Jednak jest to trochę denerwujące, jeśli chcesz udostępnić bitset na wielu platformach. Poza obciążeniem serializacji Java, BitSet jest przechowywany w jednostkach po 8 bajtów. Może to generować zbyt duży narzut, jeśli twój bitset jest mały.

Napisaliśmy tę małą klasę, dzięki czemu możemy wysyłać tablice bajtów z BitSet. W zależności od twojego zastosowania, może on działać lepiej niż serializacja Java dla Ciebie.

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