How to read a binary file into a vector of unsigned chars
When testing for performance, I would include a test case for:
std::vector<BYTE> readFile(const char* filename)
{
// open the file:
std::ifstream file(filename, std::ios::binary);
// Stop eating new lines in binary mode!!!
file.unsetf(std::ios::skipws);
// get its size:
std::streampos fileSize;
file.seekg(0, std::ios::end);
fileSize = file.tellg();
file.seekg(0, std::ios::beg);
// reserve capacity
std::vector<BYTE> vec;
vec.reserve(fileSize);
// read the data:
vec.insert(vec.begin(),
std::istream_iterator<BYTE>(file),
std::istream_iterator<BYTE>());
return vec;
}
My thinking is that the constructor of Method 1 touches the elements in the vector
, and then the read
touches each element again.
Method 2 and Method 3 look most promising, but could suffer one or more resize
's. Hence the reason to reserve
before reading or inserting.
I would also test with std::copy
:
...
std::vector<byte> vec;
vec.reserve(fileSize);
std::copy(std::istream_iterator<BYTE>(file),
std::istream_iterator<BYTE>(),
std::back_inserter(vec));
In the end, I think the best solution will avoid operator >>
from istream_iterator
(and all the overhead and goodness from operator >>
trying to interpret binary data). But I don't know what to use that allows you to directly copy the data into the vector.
Finally, my testing with binary data is showing ios::binary
is not being honored. Hence the reason for noskipws
from <iomanip>
.
Read binary file into unsigned char vector buffer
const std::vector<unsigned char> buffer(bufferSize);
You declared a const
object here. By definition, a const
object cannot be modified. Your plans to modify this object, by reading something into it, are already doomed to a big, abysmal, failure at this point. But there's also a second problem.
file.read(buffer.data(), bufferSize);
If you actually read your compiler's error message, slowly, it tells you exactly what the problem is.
First of all, read()
s first parameter is a char *
, a pointer to a character.
But you are passing a const unsigned char *
. That's because data()
, given that buffer
is const
, obviously returns a const unsigned char *
.
And that's why you get a compilation error. If you now reread the compilation error, skipping about half of its words, it makes perfect sense now:
Cannot initialize a parameter of type ... 'char *' with an rvalue of
type ... 'const unsigned char *'
To fix it, your buffer
should not be a const
object. Preferrably, it should be a std::vector<char>
, so you end up really passing a char *
to read()
.
But, if you insist, you can keep it a vector of unsigned char
s and use reinterpret_cast
to cast the result of data()
from unsigned char *
to char *
.
Read a binary file into a std::vector uint16_t instead of std::vector char
With c++11, you can use the data()
member of std::vector
and read all of file (or big chunks, if the file is too big).
Something like
#include <vector>
#include <fstream>
#include <iostream>
using myType = uint16_t;
int main ()
{
std::ifstream is;
std::vector<myType> rawfilebuffer;
is.open("uint16_t_file.raw", std::ios::binary);
is.seekg(0, std::ios::end);
size_t filesize=is.tellg();
is.seekg(0, std::ios::beg);
rawfilebuffer.resize(filesize/sizeof(myType));
is.read((char *)rawfilebuffer.data(), filesize);
for ( auto const & ui : rawfilebuffer )
std::cout << '[' << ui << ']';
std::cout << '\n';
return 0;
}
Attention to the file size. If it's an exact multiple of sizeof(myType)
, well.
Otherwise, you should modify you resize instruction in this way
rawfilebuffer.resize(filesize/sizeof(myType)+(filesize%sizeof(myType)?1U:0U));
std::vector unsigned char remains empty after reading binary file using std::ifstream
reserve()
allocates memory, but it doesn't register the allocated region as valid elements.
You should use resize()
to add elements and size()
to count the elements.
// reserve capacity
in.seekg(0, std::ios::end);
//fileContent.reserve(in.tellg());
fileContent.resize(in.tellg());
in.clear();
in.seekg(0, std::ios::beg);
// read into vector
//in.read(reinterpret_cast<char *>(fileContent.data()), fileContent.capacity());
in.read(reinterpret_cast<char *>(fileContent.data()), fileContent.size());
How do you read n bytes from a file and put them into a vector uint8_t using iterators?
You can use ifstream::read
for that.
std::vector<BYTE> v(100);
while ( file.read(reinterpret_cast<char*>(v.data()), 100) )
{
// Find out how many characters were actually read.
auto count = file.gcount();
// Use v up to count BTYEs.
}
Reading binary file into vector char reading less than full file
There are multiple stream iterators. The class template std::istream_iterator<T>
is for formatted input, i.e., it is going go skip leading whitespace before trying to read an object of type T
.
From the looks of it you want std::istreambuf_iterator<char>
which is used to iterate over the characters in a file, not doing any skipping.
Related Topics
Wait Until User Presses Enter in C++
How to Know If One Shared Library Depends on Another Shared Library or Not
External Library Throws Undefined Reference Errors in Qt Creator
When Are Static and Global Variables Initialized
Is There a Difference Between Universal References and Forwarding References
Why Doesn't Sfinae (Enable_If) Work for Member Functions of a Class Template
Error: Jump to Case Label in Switch Statement
Redirecting Cout to a Console in Windows
How to Solve "Unresolved Inclusion: <Iostream>" in a C++ File in Eclipse Cdt
What Is the Default Constructor for C++ Pointer
Differencebetween Std::Array and Std::Vector? When Do You Use One Over Other
How to Open an .Exe from Another C++ .Exe
Algorithm for Finding the Smallest Power of Two That's Greater or Equal to a Given Value