2009-09-04 2 views
6

BitSet을 사용하여이를 파일에 쓰고 싶습니다. writeObject 메소드를 사용하여 ObjectOutputStream을 사용하는 솔루션을 발견했습니다.Java에서 파일에 BitSet 작성

나는 내가 파일에 바이트를 작성하는 노력 자바 API에 ObjectOutputStream를 쳐다 보면서 당신은 내가 클래스를 확인하려고 다른 것들 (바이트, INT, 짧은 등)

를 쓸 수 있는지 보았다 다음 코드를 사용하여 결과를 내게 1 바이트 대신 7 바이트 파일을 제공합니다

내 질문은 파일의 처음 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(); 

감사

답변

2

다른 바이트는 유형 정보입니다.

기본적으로 ObjectOutputStream은 일부 대상 (일반적으로 파일)에 Serializable 객체를 쓰는 데 사용되는 클래스입니다. InputObjectStream에 대해 생각하면 더 합리적입니다. 그것에 readObject() 메소드가있다. Java는 인스턴스화 할 Object를 어떻게 알 수 있습니까? 쉬운 : 거기에 유형 정보가 있습니다.

+0

그래서 내가 올바르게 이해한다면 ObjectOutputStream을 사용하여 무언가를 쓸 때마다 모든 쓰기에 심각한 오버 헤드가 발생합니다. 예를 들어 int, short, byte 및 문자열을 쓸 경우 각 항목에 대해 4 세트의 추가 데이터를 얻을 수 있습니까? – Avner

+2

아니요. writeObject() 메서드 만 유형 헤더를 추가합니다. writeUTF() 메서드는 2 바이트 길이의 접두사를 추가합니다. 기본 writeXX() 메소드는 오버 헤드를 추가하지 않습니다. 자세한 내용은 API 문서를 참조하십시오. –

+1

또한 형식 정보는 개체 단위입니다. 기본적으로 기본 배열 (BitSet 등)로 구성된 객체의 경우 배열의 크기에 상관없이 오버 헤드가 일정합니다. –

1

당신은 ObjectOutputStream 밖으로 물건을 작성 할 수 있으므로 스트림으로 작성 형식에 대한 정보를 보유 객체를 재구성하는 데 필요한 데이터와 마찬가지로

는 당신이 ObjectOutputStream를 사용하지 않는, 스트림은 항상 비트 세트를 포함 할 것이라는 점을 알고 있다면 - 공간이 부족한 경우 각 비트는 BitSet의 비트에 해당하는 경우, 다음 바이트의 세트에 BitSet 변환 그런 다음 기본 스트림 (예 : FileOutputStream)에 직접 씁니다.

+0

불행히도 BitSet에는 바이트 배열로 변환 할 수있는 기본 제공 방법이 없습니다. – finnw

+0

메소드가 있습니다 : toByteArray() – clankill3r

+0

@ clankill3r : 예, toLongArray()와 함께 있지만 Java 7 이후에만 있습니다. – charlie

0

많은 다른 사람과 마찬가지로 직렬화 형식에는 매직 번호 및 버전 정보가있는 머리글이 포함되어 있습니다. ObjectOutputStreamDataOutput/OutputStream 메서드를 사용할 때 직렬화 된 데이터 (이없는 )의 중간에 배치됩니다. 일반적으로 defaultWriteObject 또는 putFields을 호출 한 후 writeObject 구현에서만 수행됩니다.

0

Java에서 저장된 비트 세트 만 사용하는 경우 직렬화가 정상적으로 작동합니다. 그러나 다중 플랫폼에서 비트 세트를 공유하려는 경우 다소 괴롭습니다. Java 직렬화의 오버 헤드 외에도 BitSet은 8 바이트 단위로 저장됩니다. 비트 집합이 작 으면 오버 헤드가 너무 많이 발생할 수 있습니다.

BitSet에서 바이트 배열을 빼낼 수 있도록이 작은 클래스를 작성했습니다. 유스 케이스에 따라 자바 직렬화보다 더 잘 작동 할 수도있다.

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]; 
    } 
} 
관련 문제