Loading a File into a Vector<Char>

Loading a file into a vectorchar

Another approach, using rdbuf() to read the whole file to a std::stringstream first:

#include <fstream>
#include <sstream>
#include <vector>
#include <string>

// for check:
#include <algorithm>
#include <iterator>
#include <iostream>

int main() {
std::ifstream file("test.cc");
std::ostringstream ss;
ss << file.rdbuf();
const std::string& s = ss.str();
std::vector<char> vec(s.begin(), s.end());

// check:
std::copy(vec.begin(), vec.end(), std::ostream_iterator<char>(std::cout));
}

Efficient way of reading a file into an std::vectorchar?

The canonical form is this:

#include<iterator>
// ...

std::ifstream testFile("testfile", std::ios::binary);
std::vector<char> fileContents((std::istreambuf_iterator<char>(testFile)),
std::istreambuf_iterator<char>());

If you are worried about reallocations then reserve space in the vector:

#include<iterator>
// ...

std::ifstream testFile("testfile", std::ios::binary);
std::vector<char> fileContents;
fileContents.reserve(fileSize);
fileContents.assign(std::istreambuf_iterator<char>(testFile),
std::istreambuf_iterator<char>());

C++, reading chars into a vectorchar from a file, character by character

Because you don't put char in your vector. Your function getMyRack() returns vector but not address of your vector. You can add method to your class board for adding char, for example:

 void board::addChar(char c){
this->myRack.push_back(c);
}

And then call this function:

 while(rackIn.get(ch) && charCount < 7){
this->addChar(ch);
}

Or change the return type of your function.

Loading a file into a vectorunsigned char

Change std::vector<char> vec; to std::vector<unsigned char> vec;

How to read a file into a vector elegantly and efficiently?

I've checked your code on my side using with mingw482.
Out of curiosity I've added an additional function f3 with the following implementation:

inline vector<char> f3()
{
ifstream fin{ filepath, ios::binary };
fin.seekg (0, fin.end);
size_t len = fin.tellg();
fin.seekg (0, fin.beg);

vector<char> coll(len);
fin.read(coll.data(), len);
return coll;
}

I've tested using a file ~90M long. For my platform the results were a bit different than for you.

  • f1() ~850ms
  • f2() ~600ms
  • f3() ~70ms

The results were calculated as mean of 10 consecutive file reads.

The f3 function takes the least time since at vector<char> coll(len); it has all the required memory allocated and no further reallocations need to be done. As to the back_inserter it requires the type to have push_back member function. Which for vector does the reallocation when capacity is exceeded. As described in docs:

push_back

This effectively increases the container size by one, which causes an
automatic reallocation of the allocated storage space if -and only if-
the new vector size surpasses the current vector capacity.

Among f1 and f2 implementations the latter is slightly faster although both use the back_inserter. The f2 is probably faster since it reads the file in chunks which allows some buffering to take place.

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 chars and use reinterpret_cast to cast the result of data() from unsigned char * to char *.

Load data into std::vectorchar efficiently

Is there any way to tell the v2 vector that its internal memory buffer is loaded with data?

No.

The behaviour of your second example is undefined.

This would be useful when you want to use a std::vector to hold data that is sourced from a file stream.

You can read a file into vector like this:

std::vector<char> v3(count);
ifs.read(v3.data(), count);

Or like this:

using It = std::istreambuf_iterator<char>;
std::vector<char> v4(It{ifs}, It{});

How to read a file into vector in C++?

Your loop is wrong:

for (int i=0; i=((Main.size())-1); i++) {

Try this:

for (int i=0; i < Main.size(); i++) {

Also, a more idiomatic way of reading numbers into a vector and writing them to stdout is something along these lines:

#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <algorithm> // for std::copy

int main()
{
std::ifstream is("numbers.txt");
std::istream_iterator<double> start(is), end;
std::vector<double> numbers(start, end);
std::cout << "Read " << numbers.size() << " numbers" << std::endl;

// print the numbers to stdout
std::cout << "numbers read in:\n";
std::copy(numbers.begin(), numbers.end(),
std::ostream_iterator<double>(std::cout, " "));
std::cout << std::endl;

}

although you should check the status of the ifstream for read errors.



Related Topics



Leave a reply



Submit