Calculate the crc32 of the contents of a file using boost I'm computing the crc32 of a given file using boost:

uint32_t crc32(const std::string &amp;fp){
    boost::crc_32_type result;
    std::ifstream is{fp, std::ios::in | std::ios::binary};
    size_t file_size = is.tellg();
    is.seekg(0, std::ios::beg);
    std::vector&lt;char&gt; buf(file_size);
    is.read(&amp;buf[0], file_size);

    result.process_bytes(&amp;buf[0], file_size);
    return result.checksum();
}


I believe this code is correct, but it seems unecssarily verbose, and does 2 passes over the data.

Ideally I'd like to write something like:


uint32_t crc32(const std::string &amp;fp){
    boost::crc_32_type result;
    std::ifstream is{fp, std::ios::in | std::ios::binary};
    size_t file_size = is.tellg();
    result.process_block(std::istreambuf_iterator&lt;char&gt;{is}, {}); //invalid
    return result.checksum();
}



But I'm not sure there's a valid way to convert the iterator to char *.

The final alternative I tried was:


for(uint8_t b : std::istreambuf_iterator&lt;char&gt;{is}){ //invalid
    result.process_byte(b);
}
return result.checksum();



But I'm unclear how to get a range from a istreambuf_iterator.
You seem to be missing a seek to the end.

This will always be zero.

    std::ifstream is{fp, std::ios::in | std::ios::binary};
    size_t file_size = is.tellg();


You need to add a seek to end:

    std::ifstream is{fp, std::ios::in | std::ios::binary};
    is.seekg(0, std::ios::end);
    size_t file_size = is.tellg();


There are other functions that query the file system to get the size. But You should note this does NOT do a scan of the file it just moves the descriptor to the end. So its not like reading the file.

You could just wrap it.

std::size_t fileSize(std::ifstream&amp; file)
{
    std::streampos current = file.tellg();
    file.seek(0, std::ios::end);
    std::size_t result = file.tellg();
    file.seek(current, std::ios::beg);
    return result;
}


Now your function becomes:

std::uint32_t crc32(const std::string &amp;fp)
{
    std::ifstream is{fp, std::ios::in | std::ios::binary};
    std::size_t file_size = fileSize(is);

    std::vector&lt;char&gt; buf(file_size);
    is.read(&amp;buf[0], file_size);

    boost::crc_32_type result;
    result.process_bytes(&amp;buf[0], file_size);

    return result.checksum();
}


The problem with this is that some files are huge. You don't want to read the whole thing into memory like that. So you could define a reasonable size buffer and read chunks at a time.

 std::vector&lt;char&gt;   buffer(4096);

 while(is.read(&amp;buffer[0], buffer.size()))
 {
     std::size_t count = is.gcount();
     result.process_bytes(&amp;buffer[0], count);
 }


Or you could use a memory mapped file:

Its been a while since I did this. Here are some instructions.

https://www.safaribooksonline.com/library/view/linux-system-programming/0596009585/ch04s03.html