2011-01-12 17 views
5

How to write bitset data to a file?Làm thế nào để lưu trữ một vector <bool> hoặc một bitet vào một tệp, nhưng bit-khôn ngoan?

Câu trả lời đầu tiên không trả lời đúng câu hỏi vì phải mất khoảng 8 lần không gian.

Bạn sẽ làm như thế nào? Tôi thực sự cần nó để tiết kiệm rất nhiều giá trị đúng/sai.

+0

Thực ra tôi không quan tâm rằng nó lưu trữ từng bit như một byte trong câu hỏi của tôi ... nó chỉ được diễn đạt một cách mơ hồ. Câu hỏi tiếp theo tốt. –

Trả lời

5

Cách tiếp cận đơn giản nhất: lấy 8 giá trị boolean liên tiếp, đại diện cho chúng dưới dạng một byte, ghi byte đó vào tệp của bạn. Điều đó sẽ tiết kiệm rất nhiều không gian.

Khi bắt đầu tệp, bạn có thể viết số giá trị boolean bạn muốn ghi vào tệp; con số đó sẽ giúp đỡ trong khi đọc các byte từ tập tin, và chuyển đổi chúng trở lại thành các giá trị boolean!

-1

Hai tùy chọn:

Chi tiêu thêm một pound (hoặc nhiều hơn) cho đĩa lớn hơn.

Viết một thường trình để trích xuất 8 bit từ bitet tại một thời điểm, soạn chúng thành các byte và ghi chúng vào luồng đầu ra của bạn.

+0

Tôi cũng muốn lưu trữ nhiều nhất có thể, do đó tăng khả năng của một yếu tố 8 là tốt hơn mua mua mua. – jokoon

+1

Không phải là rất hữu ích ở tất cả ... –

1

Một cách có thể là:

std::vector<bool> data = /* obtain bits somehow */ 

// Reserve an appropriate number of byte-sized buckets. 
std::vector<char> bytes((int)std::ceil((float)data.size()/CHAR_BITS)); 

for(int byteIndex = 0; byteIndex < bytes.size(); ++byteIndex) { 
    for(int bitIndex = 0; bitIndex < CHAR_BITS; ++bitIndex) { 
     int bit = data[byteIndex * CHAR_BITS + bitIndex]; 

     bytes[byteIndex] |= bit << bitIndex; 
    } 
} 

Lưu ý rằng điều này giả định bạn không quan tâm những gì bố trí chút kết thúc lên được trong bộ nhớ, vì nó làm cho không có điều chỉnh cho bất cứ điều gì. Nhưng miễn là bạn cũng tuần tự hóa số bit thực sự được lưu trữ (bao gồm các trường hợp bạn có số bit không phải là bội số của CHAR_BITS), bạn có thể deserialize chính xác cùng một bitet hoặc vectơ như ban đầu bạn đã từng .

(Tôi không hài lòng với tính toán kích thước thùng đó nhưng lúc 1 giờ sáng và tôi đang gặp sự cố khi suy nghĩ về điều gì đó thanh lịch hơn).

1

Đây là một thử với hai hàm sẽ sử dụng số byte tối thiểu, mà không cần nén bitet.

template<int I> 
void bitset_dump(const std::bitset<I> &in, std::ostream &out) 
{ 
    // export a bitset consisting of I bits to an output stream. 
    // Eight bits are stored to a single stream byte. 
    unsigned int i = 0; // the current bit index 
    unsigned char c = 0; // the current byte 
    short bits = 0;  // to process next byte 
    while(i < in.size()) 
    { 
     c = c << 1;  // 
     if(in.at(i)) ++c; // adding 1 if bit is true 
     ++bits; 
     if(bits == 8) 
     { 
      out.put((char)c); 
      c = 0; 
      bits = 0; 
     } 
     ++i; 
    } 
    // dump remaining 
    if(bits != 0) { 
     // pad the byte so that first bits are in the most significant positions. 
     while(bits != 8) 
     { 
      c = c << 1; 
      ++bits; 
     } 
     out.put((char)c); 
    } 
    return; 
} 

template<int I> 
void bitset_restore(std::istream &in, std::bitset<I> &out) 
{ 
    // read bytes from the input stream to a bitset of size I. 
    /* for debug */ //for(int n = 0; n < I; ++n) out.at(n) = false; 
    unsigned int i = 0;   // current bit index 
    unsigned char mask = 0x80; // current byte mask 
    unsigned char c = 0;   // current byte in stream 
    while(in.good() && (i < I)) 
    { 
     if((i%8) == 0)   // retrieve next character 
     { c = in.get(); 
      mask = 0x80; 
     } 
     else mask = mask >> 1; // shift mask 
     out.at(i) = (c & mask); 
     ++i; 
    } 
} 

Lưu ý rằng có thể sử dụng một reinterpret_cast của phần bộ nhớ được sử dụng bởi bitset như một loạt các ký tự cũng có thể làm việc, nhưng nó là có lẽ hệ thống accross không di động bởi vì bạn không biết những gì các đại diện của bitet là (endianness?)

2

Nếu bạn muốn lớp bitet hỗ trợ tốt nhất chuyển đổi thành nhị phân và bitet của bạn lớn hơn kích thước của unsigned long, thì tùy chọn tốt nhất để sử dụng là boost::dynamic_bitset. (Tôi đoán nó là hơn 32 và thậm chí 64 bit nếu bạn lo ngại về tiết kiệm không gian).

Từ dynamic_bitset bạn có thể sử dụng to_block_range để ghi các bit vào loại tích phân cơ bản. Bạn có thể xây dựng lại dynamic_bitset từ các khối bằng cách sử dụng from_block_range hoặc hàm tạo của nó từ BlockInputIterator hoặc bằng cách thực hiện các hàm append().

Bây giờ bạn có các byte ở định dạng gốc của chúng (Chặn) bạn vẫn gặp sự cố khi ghi nó vào luồng và đọc lại.

Trước tiên, bạn cần phải lưu trữ một chút thông tin "tiêu đề": số lượng khối bạn có và có khả năng là kết thúc.Hoặc bạn có thể sử dụng macro để chuyển đổi thành chuẩn endianness (ví dụ: ntohl nhưng bạn sẽ sử dụng lý tưởng macro là no-op cho nền tảng phổ biến nhất của bạn, vì vậy nếu đó là nhỏ, bạn có thể muốn lưu trữ theo cách đó và chỉ chuyển đổi hệ thống lớn-endian).

(Lưu ý: Tôi giả định rằng tăng :: dynamic_bitset tiêu chuẩn chuyển đổi các loại không tách rời theo cùng một cách bất kể endianness cơ bản. Tài liệu của họ không nói).

Để viết số nhị phân vào luồng sử dụng os.write(&data[0], sizeof(Block) * nBlocks) và để sử dụng là đọc. read(&data[0], sizeof(Block) * nBlocks) nơi dữ liệu được giả định là vector<Block> và trước khi đọc, bạn phải làm data.resize(nBlocks) (không phải reserve()). (Bạn cũng có thể làm những thứ kỳ lạ với istream_iterator hoặc istreambuf_iterator nhưng thay đổi kích thước() có lẽ tốt hơn).

+1

Tôi đã làm một số mã với một vector >, tôi sẽ kiểm tra nó sau – jokoon

0
#include "stdio" 
#include "bitset" 
... 
FILE* pFile; 
pFile = fopen("output.dat", "wb"); 
... 
const unsigned int size = 1024; 
bitset<size> bitbuffer; 
... 
fwrite (&bitbuffer, 1, size/8, pFile); 
fclose(pFile);