0x0
0x0

Reputation: 3075

How can I read multiple bytes from a file at a time?

I want to read 8byte chunks from a binary file at a time till I reach end of the file. Why doesn't this code work? What are the alternatives?

// read a file into memory
#include <iostream>
#include <fstream>
using namespace std;

int main () {

  long long int * buffer;

  ifstream is;
  is.open ("test.txt", ios::binary );

  // allocate memory:
  buffer = new long long int;

  // read data:
  while(!is.eof())
      is.read (buffer,sizeof(long long int));
  is.close();


  delete[] buffer;
  return 0;
}

If I replace all long long int with char, the code works perfectly.

Ref: code adapted from www.cplusplus.com

Upvotes: 2

Views: 3627

Answers (3)

Roger Pate
Roger Pate

Reputation:

The problem is !eof: it tells you whether the last operation hit eof, not whether the next will, and not whether the last failed!

Test the stream's truthiness itself (or use the fail method which is the same thing, negated), after doing the IO:

while (is.read(buffer, sizeof(long long int))) {
  // use buffer
}
assert(is.fail());  // must be true

Additionally, you don't have to use new at all:

long long buffer;
// ...
is.read(reinterpret_cast<char*>(&buffer), sizeof buffer)
  // the reinterpret_cast is needed in your original code too

Your source, cplusplus.com, also fails to check whether the read succeeded before using the data. In general, I find that site great for listing parameters, methods, etc. and horrible for most else.


Putting it all together, with some example output:

#include <climits>
#include <fstream>
#include <iomanip>
#include <iostream>

int main () {
  using namespace std;

  ifstream in ("test.txt", in.binary);
  cout << hex << setfill('0');
  for (long long buffer;
       in.read(reinterpret_cast<char*>(&buffer), sizeof buffer);)
  {
    cout << setw(sizeof buffer * CHAR_BIT / 4) << buffer << '\n';
  }

  return 0;
}

Upvotes: 3

Reinderien
Reinderien

Reputation: 15211

Another way to do the buffer allocation is with a union. This removes the need for casting.

#include <iostream>
#include <fstream>
using namespace std;

int main ()
{
    union
    {
        long long int n;
        char ch[sizeof(long long int)];
    } buffer;

    ifstream is("test.txt", ios::binary);

    while (is.read(buffer.ch,sizeof(buffer)))
        cout << buffer.n << '\n';

    return 0;
}

Upvotes: 1

Alexander Rafferty
Alexander Rafferty

Reputation: 6233

char buffer[8];
while (in.read(buffer,8)) {
    long long data = *(reinterpret_cast<long long*>(buffer));
    // process data
}

This is probably what you are looking for.

Upvotes: 0

Related Questions