-1

I'm making a sorting algorithm in C++ that gets data from a binary file. The file only contains unsigned int and the first 4byte of the file show the number of elements it has. Next 4byte chunks has the unsigned integer gotta be sorted.

    ifstream ifs(INPUT_FILE_NAME,ios::binary);
    ifs.seekg(0,ifs.end);
    int N=0;
    N=(int)ifs.tellg();
    vector<unsigned int> buf(N / sizeof(unsigned int));// reserve space for N/4 unsigned int
    ifs.read(reinterpret_cast<char*>(buf.data()), buf.size()*sizeof(unsigned int)); // char==byte

I referenced a question "how to efficiently read a binary file into a vector C++", So, I tried to get bin file exactly into the vector. But I have no idea how to deal with it. I tried to cast char into uint but it didn't work. Can you give me a hint to make it?

  • 2
    Also, since you are using the first 4 bytes of the file to provide the number of integers, you should rely on it for the size of the vector (you could double check with the file size) and skip it before adding the elements to the vector. Having the number of elements as the first value in the vector is counter productive as your first operation would be to remove it which would copy the whole vector. – Alex Apr 11 '23 at 20:43
  • 1
    You don't really need a count, if you trust the size of the file. – Paul Sanders Apr 11 '23 at 20:44
  • 1
    And you trust seek and tell to be implemented in a normal fashion. All they actually offer is the ability to return to a point in a stream, so you can get some deviant implementations that cannot be used to compute the size of a file. Don't know if I've seen one in the wild, though. – user4581301 Apr 11 '23 at 20:46
  • Thank you! Ill try getting first 4bytes! – AmiablePrism30 Apr 11 '23 at 20:49
  • 2
    For getting the file size, if you have C++17, there is this: https://en.cppreference.com/w/cpp/filesystem/file_size – Paul Sanders Apr 11 '23 at 20:50
  • Stackoverflow usage note: Avoid writing "It doesn't work" without describing how the behaviour you got deviated from the behaviour you expected. – user4581301 Apr 11 '23 at 20:51
  • Did you check that `unsigned int` is 32 bits on your system? Always worth validating. – Martin York Apr 11 '23 at 22:49

1 Answers1

2

You are seeking ifs to the end of the file, but you forgot to seek it back to the beginning before calling read(), so there is nothing for read() to read. You need that 2nd seek, eg:

ifstream ifs(INPUT_FILE_NAME,ios::binary);

ifs.seekg(0, ifs.end);
size_t N = ifs.tellg();
ifs.seekg(0, ifs.beg); // <-- ADD THIS!

For that matter, why are you seeking ifs at all? You said the 1st unsigned int in the file tells you the number of subsequent unsigned ints to read, so just read from ifs without seeking it at all, eg:

ifstream ifs(INPUT_FILE_NAME, ios::binary);

uint32_t N = 0;
ifs.read(reinterpret_cast<char*>(&N), sizeof(uint32_t));

vector<uint32_t> buf(N);
ifs.read(reinterpret_cast<char*>(buf.data()), N * sizeof(uint32_t));

In which case, the 1st unsigned int becomes redundant if you are able to remove it, as you could just ask the filesystem for the file's size, eg:

ifstream ifs(INPUT_FILE_NAME, ios::binary);

vector<uint32_t> buf(filesystem::file_size(INPUT_FILE_NAME) / sizeof(uint32_t));
ifs.read(reinterpret_cast<char*>(buf.data()), buf.size() * sizeof(uint32_t));

Or, simply read from the file until EOF is reached, eg:

ifstream ifs(INPUT_FILE_NAME, ios::binary);

vector<uint32_t> buf;
buf.reserve(filesystem::file_size(INPUT_FILE_NAME) / sizeof(uint32_t));

uint32_t number;
while (ifs.read(reinterpret_cast<char*>(&number), sizeof(uint32_t)) {
    buf.push_back(number);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770