2009-09-04 41 views
6

Tôi có một BitSet và muốn viết nó vào một tập tin- Tôi đã xem qua một giải pháp để sử dụng một ObjectOutputStream bằng cách sử dụng phương thức writeObject.viết một BitSet vào một tập tin trong java

Tôi nhìn ObjectOutputStream trong API java và thấy rằng bạn có thể viết những thứ khác (byte, int, ngắn vv)

Tôi cố gắng để kiểm tra lớp vì vậy tôi cố gắng viết một byte vào một tập tin sử dụng mã sau nhưng kết quả cho tôi một tệp có 7 byte thay vì 1 byte

câu hỏi của tôi là 6 byte đầu tiên trong tệp là gì? tại sao họ lại ở đó?

câu hỏi của tôi có liên quan đến một BitSet vì tôi không muốn bắt đầu viết nhiều dữ liệu vào một tệp và nhận ra tôi có byte ngẫu nhiên được chèn vào tệp mà không biết chúng là gì.

đây là mã:

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

nhờ sự giúp đỡ nào

Avner

Trả lời

2

Các byte khác sẽ là thông tin loại.

Về cơ bản ObjectOutputStream là một lớp được sử dụng để ghi các đối tượng có thể tuần tự đến một số đích (thường là một tệp). Nó có ý nghĩa hơn nếu bạn nghĩ về InputObjectStream. Nó có phương thức readObject() trên đó. Làm thế nào để Java biết Object cần làm gì? Dễ dàng: có loại thông tin trong đó.

+0

vì vậy nếu tôi hiểu bạn một cách chính xác - mỗi khi tôi viết một cái gì đó bằng cách sử dụng ObjectOutputStream tôi nhận được chi phí nghiêm trọng cho mỗi viết. ví dụ nếu tôi viết một int, một đoạn ngắn, một byte và sau đó một chuỗi Tôi nhận được 4 bộ dữ liệu bổ sung cho mỗi mục tôi viết? – Avner

+2

Không. Chỉ có phương thức writeObject() mới thêm tiêu đề kiểu. Phương thức writeUTF() thêm một tiền tố chiều dài 2 byte. Các phương thức writeXX() nguyên thủy không thêm bất kỳ chi phí nào. Đọc tài liệu API để biết chi tiết. –

+1

Cũng lưu ý rằng thông tin loại là cho mỗi đối tượng. Đối với một đối tượng bao gồm cơ bản của một mảng nguyên thủy (chẳng hạn như BitSet), chi phí là hằng số, bất kể mảng lớn như thế nào. –

1

Bạn có thể viết bất kỳ đối tượng ra một ObjectOutputStream, vì vậy dòng chứa thông tin về các loại văn bản như cũng như dữ liệu cần thiết để hoàn nguyên đối tượng.

Nếu bạn biết rằng dòng sẽ luôn luôn chứa một BitSet, không sử dụng một ObjectOutputStream - và nếu không gian là một phí bảo hiểm, sau đó chuyển đổi BitSet đến một tập hợp các byte nơi mỗi bit tương ứng với một chút trong BitSet, sau đó viết trực tiếp vào luồng cơ bản (ví dụ: FileOutputStream như trong ví dụ của bạn).

+0

Thật không may, BitSet không có phương pháp tích hợp để chuyển đổi nó thành một mảng byte. – finnw

+0

Có phương pháp: 'toByteArray()' – clankill3r

+0

@ clankill3r: Có, cùng với 'toLongArray()', nhưng chỉ từ Java 7. – charlie

0

Định dạng tuần tự hóa, giống như nhiều định dạng khác, bao gồm tiêu đề có số thông tin và phiên bản ma thuật. Khi bạn sử dụng các phương thức DataOutput/OutputStream trên ObjectOutputStream được đặt ở giữa dữ liệu được tuần tự hóa (không có thông tin loại). Điều này thường chỉ được thực hiện sau khi triển khai writeObject sau khi gọi đến defaultWriteObject hoặc sử dụng putFields.

0

Nếu bạn chỉ sử dụng BitSet đã lưu trong Java, việc tuần tự hóa hoạt động tốt. Tuy nhiên, đó là loại gây phiền nhiễu nếu bạn muốn chia sẻ các bitet trên nhiều nền tảng. Bên cạnh phần đầu của tuần tự hóa Java, BitSet được lưu trữ theo đơn vị 8 byte. Điều này có thể tạo ra quá nhiều chi phí nếu bitet của bạn nhỏ.

Chúng tôi đã viết lớp nhỏ này để chúng tôi có thể trích xuất mảng byte từ BitSet. Tùy thuộc vào usecase của bạn, nó có thể làm việc tốt hơn so với serialization Java cho bạn.

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]; 
    } 
} 
Các vấn đề liên quan