Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write vector<unsigned char> to file, followed by an unsigned int

I have to group 5 unsigned char vectors (data_length=5). At the end of the group, I want to add an ID group and write them (group data+ its ID) to file. In which group ID types integer. I do that task as below code. Is it correct? The bellow figure shows what I am taking

enter image description here

#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 additions, I want to extract the data to vector without the group ID. This is my code to extract data from the above file, but it does not remove the ID group. Could you help me to 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>());
like image 339
Jame Avatar asked Jan 12 '16 06:01

Jame


1 Answers

First of all, you use while, where for would be easier to read. BTW. you don't need two iteration variables. It is fine to iterate over ID_data.

for( unsigned int ID_data = 0; ID_data < 10; ++ID_data ) {
    // ...
}

second you don't need to produce a vector, that you never reuse, and then write the elements. It is fine do directly write the values.

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

The second part: You can instantiate 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 only read data_length values you might 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.
}
like image 150
cdonat Avatar answered Oct 30 '22 11:10

cdonat