C++ c_str doesn't return entire string
Question
I've tried the following code with both normal ifstreams and the current boost:iostream I'm using, both have the same result.
It is intended to load a file from physfs into memory then pass it to a handler to process (eg Image, audio or data). Currently when c_str is called it only returns a small part of the file.
PhysFS::FileStream file("Resources/test.png" , PhysFS::OM_READ);
if(file.is_open()) {
String* theFile;
theFile = new String((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
String::iterator it;
for ( it=theFile->begin() ; it < theFile->end(); it++ ) {
std::cout << *it;
} // Outputs the entire file
std::cout << theFile->c_str(); // Outputs only the first few lines
}
The iterator loop outputs the entire png file as expected, but the c_str call only returns the first few characters (\211PNG).
I've been trying variations of this code for quite some time with no success. Any ideas?
Solution
I imagine that the next character is a null (ASCII 0) byte. c_str() simply gives you a *char, therefore your write to stdout is interpreted as a class C string which ends at the first null byte.
If you really need a C-like interface to this string, the main thing is that theFile->c_str() points to your data and theFile.length gives you the number of characters in the string. So you might want to do something like this:
char *c_value = theFile->c_str()
for (int i = 0; i < theFile.length; i++)
{
cout << c_value[i];
}
The real solution depends on why you are converting to a char * in the first place. If you are calling a legacy function that only accepts char *, there is likely also a length argument to that legacy function.
OTHER TIPS
One of the bytes is probably 0. That means end of string to cout when passing a char* (which c_str is)
I would consider using std::vector<unsigned char>
instead of std::string
for this. It is a lot easier to deal with binary data in a vector. You can reference the underlying pointer using &vec[0]
if you need access to a C-style array. I would also make sure that your file abstraction use std::ios_base::binary
for the file mode under the hood as well.