How to write a <unsigned char> vector to a file followed by unsigned int
I need to group 5 unsigned char vectors ( data_length=5 ). At the end of the group I want to add a group of identifiers and write them (group data + its identifier) โโto a file. What are the identifiers of the integer group. I am performing this task as shown below. Is it correct? The bottom figure shows that I accept
#define random(x) (rand()%x) std::ofstream filewrite("abc.raw", std::ios::out | std::ofstream::binary); unsigned int iter = 0; unsigned int data_length=5; unsigned int ID_data=0; //-------------Write data-------------// while (iter<10){ vector<unsigned char> vec_data; for (unsigned int i=0;i<data_length;i++){ vec_data.push_back(random(256)) } std::copy(vec_data.begin(), vec_data.end(), std::ostreambuf_iterator<char>(filewrite)); //Write ID_data after vec_data filewrite.write(reinterpret_cast<const char *>(&ID_data), sizeof(ID_data)); ID_data++; iter++; } filewrite.close(); In addition, I want to extract data into a vector without a group identifier. This is my code for extracting data from the above file, but it does not delete the identifier group. Could you help me remove it?
//-------------Read data-------------// std::ifstream file("abc.raw", std::ios::binary); // Stop eating new lines in binary mode!!! file.unsetf(std::ios::skipws); // get its size: std::streampos fileSize; file.seekg(0, std::ios::end); fileSize = file.tellg(); file.seekg(0, std::ios::beg); // reserve capacity std::vector<unsigned char> vec; vec.insert(vec.begin(), std::istream_iterator<unsigned char>(file), std::istream_iterator<unsigned char>()); First of all, you use while , where for will be easier to read. BTW. you do not need two iteration variables. It is ok to iterate over ID_data .
for( unsigned int ID_data = 0; ID_data < 10; ++ID_data ) { // ... } second you do not need to create a vector that you will never reuse, and then write the elements. This is normal; write values โโdirectly.
for( unsigned int ID_data = 0; ID_data < 10; ++ID_data ) { for( unsigned int i = 0; i < data_length; i++ ) filewrite.put(random(256)); filewrite.write(reinterpret_cast<const char *>(&ID_data), sizeof(ID_data)); } Second part: you can create a vector with two iterators.
auto vec = std::vector<unsigned char>(std::istream_iterator<unsigned char>{file}, std::istream_iterator<unsigned char>{}); But since you want to read only those data_length values โโthat you may prefer:
auto vec = std::vector<unsigned char>{}; while( file ) { for( unsigned int i = 0; i < data_length; i++ ) { char c; if( !file.get(c) ) break; vec.push_back(static_cast<unsigned char>(c)); } unsigned int ID_data; file.read(reinterpret_cast<const char *>(&ID_data), sizeof(ID_data)); // we don't use ID_data here, so it will simply be ignored. } I'm not sure I understood your question correctly. Since I assume you have problems with binary notation, I give you a solution for only one vector. You can easily change it:
void Write( std::ostream& os, const std::vector< std::uint8_t >& v, const std::int32_t id ) { std::size_t len = v.size(); os.write( (const char*)&len, sizeof len ); for ( auto e : v ) os.write( (const char*)&e, sizeof e ); os.write( (const char*)&id, sizeof id ); } void Read( std::istream& is, std::vector< std::uint8_t >& v ) { std::size_t len; is.read( (char*)&len, sizeof len ); v.resize( len ); for ( auto &e : v ) is.read( (char*)&e, sizeof e ); std::int32_t id; is.read( (char*)&id, sizeof id ); } int main() { // write { std::ofstream os( "abc.raw", std::ios::binary ); if ( ! os ) return -1; std::vector< std::uint8_t > v; v.push_back( 0x10 ); v.push_back( 0x20 ); v.push_back( 0x30 ); Write( os, v, 0x123 ); } // read { std::ifstream is( "abc.raw", std::ios::binary ); if ( ! is ) return -1; std::vector< std::uint8_t > v; Read( is, v ); } // return 0; } 