tags:

views:

172

answers:

5

I have a big file full of integers that I'm loading in. I've just started using C++, and I'm trying out the filestream stuff. From everything I've read, it appears I can only read in bytes, So I've had to set up a char array, and then cast it as a int pointer.

Is there a way I can read in 4 bytes at a time, and eliminate the need for the char array?

const int HRSIZE = 129951336;  //The size of the table
char bhr[HRSIZE];   //The table
int *dwhr;

int main()
{
    ifstream fstr;

    /* load the handranks.dat file */
    std::cout << "Loading table.dat...\n";
    fstr.open("table.dat");
    fstr.read(bhr, HRSIZE);
    fstr.close();
    dwhr = (int *) bhr;    
}
+1  A: 

your can do:

int i;
fstr.read((int*)&i, sizeof(int));
mathk
+6  A: 

To read a single integer, pass in the address of the integer to the read function and ensure you only read sizeof int bytes.

int myint;

//...

fstr.read(reinterpret_cast<char*>(&myint), sizeof(int));

You may also need to open the file in binary mode

fstr.open("table.dat", std::ios::binary);
Yacoby
+1 for C++ answer instead of unsafe C-style casts
Daniel
@Daniel: `reinterpret_cast` is no 'safer' than a C-style cast.
John Dibling
It's equally safe at runtime, but safer when you read the code on a Sunday night before a deadline.
MSalters
If you want to read raw integers, you need to deal with endian issues. One technique is to store in network endian order which means you use `htonl` before writing and `ntohl` after reading.
R Samuel Klatchko
A: 

Is this what you mean? By the way, your code (and this) assumes native endianness of the data.

const int HRSIZE = 129951336;  //The size of the table
int dhr[HRSIZE/sizeof(int)];   //The table

int main()
{
    ifstream fstr;

    /* load the handranks.dat file */
    std::cout << "Loading table.dat...\n";
    fstr.open("table.dat");
    fstr.read((char*)dhr, HRSIZE);
    fstr.close();
}
Mark Borgerding
A: 

You could try this:

const int HRSIZE = 129951336/sizeof(int);  //The size of the table
int bhr[HRSIZE];   //The table

int main(int argc, char *argv[])
{
    ifstream fstr;

    /* load the handranks.dat file */
    std::cout << "Loading table.dat...\n";
    fstr.open("table.dat");
    for (int i=0; i<HRSIZE; ++i)
    {
        fstr.read((char *)(bhr+i), sizeof(int));
    }
    fstr.close();

    // for correctness
    return 0;
}
Amardeep
+3  A: 

To read by 4 bytes from ifstream you could overload operator>> as follows (it is actually a partial specialization of the basic_istream class template so istream_iterator could use operator>> from it. Class basic_ifstream is used here to inherit all input file stream functionality from it):

#include <fstream>

typedef unsigned int uint32_t;    
struct uint32_helper_t {};

namespace std {
template<class traits>
class basic_istream<uint32_helper_t, traits> : public basic_ifstream<uint32_t> {
public:
    explicit basic_istream<uint32_helper_t, traits>(const char* filename, 
        ios_base::openmode mode ) : basic_ifstream<uint32_t>( filename, mode ) {}

    basic_istream<uint32_helper_t, traits>& operator>>(uint32_t& data) {
        read(&data, 1);
        return *this;
    }
};
} // namespace std {}

Then you could use it in the following way:

std::basic_istream<uint32_helper_t> my_file( FILENAME, std::ios::in|std::ios::binary );
// read one int at a time
uint32_t value;
my_file >> value;

// read all data in file
std::vector<uint32_t> data;
data.assign( std::istream_iterator<uint32_t, uint32_helper_t>(my_file),
  std::istream_iterator<uint32_t, uint32_helper_t>() );
Kirill V. Lyadvinsky
+1: for the STL-ish approach :)
Kornel Kisielewicz
@camh, the code explains the idea. We overload `operator>>` here for our type. Then use it explicitly in the first case and implicitly in the second case. What part of it is not clear?
Kirill V. Lyadvinsky
There's more than an overloaded operator there. I cant see why you have basic_istream inheriting from basic_ifstream. It also doesn't compile (g++ 4.4.4).
camh
@camh, I've added extra explanations in my answer. And I've made some fixes to make it more conformant. Hope this will help.
Kirill V. Lyadvinsky
Ok. I've removed the -1. The problem must be in my head somewhere. I can't understand how basic_istream can inherit from basic_ifstream, since basic_ifstream already inherits from basic_istream.
camh
The trick is that this is partial specialization of `basic_istream` template class, not standard `basic_istream`.
Kirill V. Lyadvinsky