Reputation: 1032
I am attempting to read a file of unsigned characters into a vector. My slightly roundabout way of doing this is by creating an input file stream, reading that data into a stringstream, and initializing a vector using the contents of the stringstream. There is probably a much better way to do this, and my existing code causes a segmentation fault using certain files.
string file_name = "output/comp" + to_string(start_id) + ".xml";
if( !file_exists(file_name))
{
cout << "File could not be found." << endl;
return 0;
}
ifstream ifs(file_name);
stringstream ss;
ss << ifs.rdbuf();
ss >> noskipws;
vector<unsigned char> raw_data(ss.str().begin(), ss.str().end());
I have included all the necessary headers and using
declarations, and file_exists()
returns a boolean value indicating whether or not the file exists.
My question is this: Why is the above code incorrect, and what is the best method for correctly accomplishing the same objective?
Upvotes: 0
Views: 5149
Reputation: 180630
The problem with
vector<unsigned char> raw_data(ss.str().begin(), ss.str().end());
is that str()
returns a temporary string. This means the string
you use for begin
is not the same string
you use for end
. Since the iterators do not refer to the same string
you cannot use them together.
Instead of using a strignstream
we can read the file directly into the vector using istream_iterator
s like
std::ifstream ifs(file_name);
std::istream_iterator<unsigned char> start(ifs), end;
std::vector<unsigned char> raw_data(start, end);
Upvotes: 2
Reputation: 38218
std::stringstream::str()
returns a std::string
. That is, it's a temporary string.
So ss.str().begin()
returns the beginning iterator for a temporary string, and ss.str().end()
returns the ending iterator of a different temporary string, because both ss.str()
calls are returning different temporary strings. You can't mix iterators between different objects!
To fix this, use one string:
std::string str = ss.str();
And now just pass str.begin()
and str.end()
.
Upvotes: 8
Reputation: 452
i'm not exactly sure why that would cause a segfault, perhaps something in string stream, but with c++11 it's very easy to read a file into a string once you have any istream derivative:
std::string readFileAsString(std::istream& stream)
{
return std::string(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>());
}
edit sorry, I forgot you wanted the bytes at the end
return std::vector<char>(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>());
Upvotes: 0