Reading from binary file to vector of uint8_t?

Hello everybody.
i'm trying to read a binary file directly to a vector of uint8_t, but its not working. it gives me no error, just don't read anything.
heres's my code: first i create a vector with 100 elements, fill it with the number 40, and write it to the file. it works good, as i can see if i open the resulting file in a binary file viewer.
then, i re-fill the vector with the number 50. and try to read the binary file which contains only the number 40. but when i print the values of vec, it gives me the equivalent to 50.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main(){
    //Write
    std::vector<uint8_t> vec(100);
        std::fstream file("map.data", std::ios::binary);
        for (size_t n=0; n<vec.size(); n++){
            vec[n] = 40;
        }
        file.write(reinterpret_cast<char*>(&vec[0]), vec.size() * sizeof(vec[0]));
        file.close();

    //Read
    file.open("map.data", std::ifstream::binary);
    for (size_t i=0; i<vec.size(); i++){
        vec[i] = 50;
    }
    file.read(reinterpret_cast<char*> (&vec[0]), 100*sizeof(vec[0]));
    for (size_t i=0; i<vec.size(); i++){
        std::cout << vec[i] << ",";
    }
    return 0;
}


what am i possibly doing wrong?
thanks in advance.
The first thing I see wrong is that you fail to provide the correct open mode for your fstream(). You need to provide either the ::in or ::out flags along with the ::binary. With a fstream if you modify the second parameter it replaces the default open mode, it doesn't add to the default open mode.

Also since you're reusing the stream you really should also clear() any error flags. Just closing and opening a file doesn't always clear the stream errors.

not working. i changed it a bit to avoid this kind of collisions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main(){
    //Write
    std::vector<uint8_t> vec(100);
    std::ofstream w_file("map.data", std::ios::binary);
    for (size_t n=0; n<vec.size(); n++){
        vec[n] = 40;
    }
    w_file.write(reinterpret_cast<char*>(&vec[0]), vec.size() * sizeof(vec[0]));
    w_file.close();

    //Read
    std::ifstream r_file("map.data", std::ios::binary);
    r_file.open("map.data", std::ifstream::binary);
    for (size_t i=0; i<vec.size(); i++){
        vec[i] = 50;
    }
    r_file.read(reinterpret_cast<char*> (&vec[0]), 100*sizeof(vec[0]));
    for (size_t i=0; i<vec.size(); i++){
        std::cout << vec[i] << ",";
    }
return 0;
}
Last edited on
So do your changes help?
no, it's not working yet :(
Have you tried writing/reading the file one record at a time?

Is there a particular reason you're writing the files in binary/unformatted mode instead of just using text/formatted io?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdint>

int main ()
{
  // creates a vector with 100 elem and the value 40
  std::vector<uint8_t> vec (100, 40); 
  std::ofstream w_file ("map.data", std::ios::binary);

  w_file.write (reinterpret_cast<char*>(&vec[0]), vec.size () * sizeof (vec[0]));
  w_file.close ();

  //Read
  std::ifstream r_file ("map.data", std::ios::binary);
  // creates a vector with 100 elem and the value 0
  std::vector<uint8_t> vec2 (100);
  r_file.read (reinterpret_cast<char*> (&vec2[0]), 100 * sizeof (vec2[0]));
  for (size_t i = 0; i<vec2.size (); i++)
  {
    std::cout << vec2[i] << " = " << static_cast<int>(vec2[i]) << ' ';
  }
  system ("pause");
  return 0;
}


Output:
1
2
3
4
5
6
7
8
9
( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( =
 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40
 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 (
= 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 4
0 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 (
 = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( =
40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40
( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( =
 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 ( = 40 
thanks everyone, it's now working.
TheSmallGuy, i was really opening the file twice, which led to error.
jlb, i'm using binary files just because they are faster, and i need to read lots of things constantly (about ten times in a second).
and thanks for the working example, Thomas1965.

just one more thing: i tried change only from a specific point on. i thought i should use seekg, but it's doing nothing. lets say i have a 10-elements vector, and want to change 5 elements starting from the third one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main(){
    //Write
    std::vector<uint8_t> vec(10);
    std::ofstream w_file("map.data", std::ios::binary);
    for (size_t n=0; n<vec.size(); n++){
        vec[n] = 40;
    }
    w_file.write(reinterpret_cast<char*>(&vec[0]), vec.size() * sizeof(vec[0]));
    w_file.close();

    //Read
    std::ifstream r_file;
    r_file.open("map.data", std::ifstream::binary);
    for (size_t i=0; i<vec.size(); i++){
        vec[i] = 60;
    }
    r_file.seekg(3*sizeof(vec[0]));
    r_file.read(reinterpret_cast<char*> (&vec[0]), 5*sizeof(vec[0]));
    for (size_t i=0; i<vec.size(); i++){
        std::cout << vec[i] << ",";
    }
    return 0;
}
Perhaps you would be better off changing the uint8_t to an int for your vector type. It will make seeing the difference easier.

40,40,40,40,40,60,60,60,60,60,

You may also want to write different values to each element before the write to make it easier as well.

Something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <vector>
#include <fstream>
#include <iostream>

int main(){
    //Write
    std::vector<int> vec(10);
    std::ofstream w_file("map.data", std::ios::binary);
    for (size_t n=0; n<vec.size(); n++){
        vec[n] = 40 + (n * 10);
    }
    for(auto& itr : vec)
        std::cout << itr << " ";
    std::cout << std::endl;
    
    w_file.write(reinterpret_cast<char*>(&vec[0]), vec.size() * sizeof(vec[0]));
    w_file.close();

    //Read
    std::ifstream r_file;
    r_file.open("map.data", std::ifstream::binary);
    for (size_t i=0; i<vec.size(); i++){
        vec[i] = 60 + i;
    }
    r_file.seekg(3*sizeof(vec[0]));
    r_file.read(reinterpret_cast<char*> (&vec[0]), 5*sizeof(vec[0]));
    for (size_t i=0; i<vec.size(); i++){
        std::cout << vec[i] << ",";
    }
    return 0;
}


Output:
1
2
40 50 60 70 80 90 100 110 120 130 
70,80,90,100,110,65,66,67,68,69,




i use uint8_t just to avoid errors in case i'm reading this binary in another computer, since the size of int can vary. i'll probably change it to uint16_t later.

unfortunately your example does not work either. it seems seekg is doing nothing (?)
Last edited on
i use uint8_t just to avoid erros in case i'm reading this binary in another computer, since the size of int can vary.

But by sticking with a that type you're confusing yourself. By switching to an int (or int32_t) you can see that the values are changing.

unfortunately your example does not work either. it seems seekg is doing nothing (?)

What do you mean? Look closely at the second line of the output I supplied, it starts at 70, not 40 which means that the seek worked since 70 is the third element that you wrote to the file. Then you read 5 elements from the file starting at the third, 70,80,90,100, and 110, the rest of the numbers are the values that the vector contained.
Last edited on
oops, you are right! sorry, i confused myself!
thank for the help, now it's working :)
Topic archived. No new replies allowed.