2011-02-01 34 views
11

Tôi có một số std::vector<int> và tôi muốn tuần tự hóa dữ liệu đó. Với mục đích này, tôi đang cố gắng sử dụng một std::stringstreamLàm cách nào để sao chép dữ liệu nhị phân sang một chuỗi

vector<int> v; 
v.resize(10); 
for (int i=0;i<10;i++) 
v[i]=i; 


stringstream ss (stringstream::in | stringstream::out |stringstream::binary); 

Tuy nhiên khi tôi sao chép các vector đến stringstream bản sao này nó như là nhân vật

ostream_iterator<int> it(ss); 
copy(v.begin(),v.end(),it); 

giá trị mà đưa vào để đệm (_Strbuf) là "123456789 "

tôi sucssesed để viết một giải pháp workaround

for (int i=1;i<10;i++) 
    ss.write((char*)&p[i],sizeof(int)); 

tôi muốn làm điều đó một cái gì đó giống như cách thứ nhất bằng cách sử dụng chức năng std như bản sao

nhờ Herzl

Trả lời

10

Thực ra, đây là giải pháp thay thế của bạn nhưng có thể được sử dụng với thuật toán std :: copy().

template<class T> 
    struct serialize 
    { 
     serialize(const T & i_value) : value(i_value) {} 
     T value; 
    }; 

    template<class T> 
    ostream& operator <<(ostream &os, const serialize<T> & obj) 
    { 
     os.write((char*)&obj.value,sizeof(T)); 
     return os; 
    } 

Cách sử dụng

ostream_iterator<serialize<int> > it(ss); 
copy(v.begin(),v.end(),it); 
+0

Tôi thích cách tiếp cận này nói chung, nhưng thường là lỗi để bộ nhớ đầu ra mù quáng như thế này. Bạn vẫn cần phải viết một cái gì đó mà có thể tuần tự đúng từng loại. –

+0

Hoàn toàn đồng ý. Tôi sẽ không bao giờ sử dụng mã như vậy trong sản xuất. Tôi muốn sử dụng chu trình "for" được đề cập ở trên :-) – Stas

2

Tôi biết điều này không phải là một câu trả lời cho vấn đề của bạn, nhưng nếu bạn không giới hạn ở những STL bạn có thể thử (boost serialization) hoặc google protocol buffers

Tăng thậm chí có hỗ trợ tích hợp cho việc sắp xếp/đóng gói các container STL (http://www.boost.org/doc/libs/1_45_0/libs/serialization/doc/tutorial.html#stl)

+0

nhờ Omer nhưng tôi cần kết nối đến một phần cứng và như tôi thấy tăng thêm một số dữ liệu kiểm soát vào dữ liệu (loại đã phân loại) –

1

Để sử dụng tiêu chuẩn :: sao chép bằng ostream :: viết, bạn cần viết trình lặp đầu ra của riêng bạn biết cách sửa đổi tuần tự hóa loại. Điều đó nói rằng, tôi không chắc chắn những gì bạn mong đợi để đạt được từ phương pháp này, nhưng here's a first pass tại đó cho một ví dụ:

struct ostream_write_int 
    : std::iterator<std::output_iterator_tag, int, void, void, void> 
{ 
    std::ostream *s; 
    ostream_write_int(std::ostream &s) : s (&s) {} 

    ostream_write_int& operator++() { return *this; } 
    ostream_write_int& operator++(int) { return *this; } 
    ostream_write_int& operator*() { return *this; } 

    void operator=(int x) { 
    s->write(reinterpret_cast<char*>(&x), sizeof(x)); 
    } 
}; 

này có thể được templated chỉ nếu bạn hoãn logic tuần tự đối với một số chức năng khác (như trình lặp dòng được định dạng làm cho toán tử < <).

1

Giống như Fred, tôi không nhìn thấy điểm này, những gì bạn đang có hiệu quả cố gắng làm là:

ss.rdbuf()->sputn(reinterpret_cast<char*>(&v[0]), sizeof(int) * v.size()); 
+1

Điều này không dễ đọc. Tôi sẽ không bao giờ hiểu mã như vậy một cách dễ dàng. –

+0

@ the_drow, "không bao giờ" là một thời gian dài! ;), bạn có thể thay thế '.rdbuf() -> sputn (' bằng '.write (' nếu bạn muốn, nó giống nhau .. – Nim

+1

Điều này đúng cho trường hợp của một vectơ, nhưng một trình lặp mà viết mỗi mục (như trong câu trả lời của tôi hoặc của Stas) có thể được sử dụng với bất kỳ trình lặp đầu vào nào, chẳng hạn như từ danh sách std :: –

Các vấn đề liên quan