There are two ways that I know of to read file contents to a C-style string. The reason I need a C-style string and not a unique_ptr<string>
is because I will be passing this data to a C function, gumbo_parse()
whose parameter is a C-style string, and this way I avoid the overhead of a unique_ptr<string>
. I am open to arguments against my decision.
std::ifstream ifs(bf::path("...")); // Input file stream
First way:
std::filebuf * ptr_fbuff = ifs.rdbuf(); // Buffer to file contents.
std::size_t fbuff_size = ptr_fbuff->pubseekoff(0, ifs.end, std::ios_base::in); // Get offset from 0 to end of buffer.
ptr_fbuff->pubseekpos(0, std::ios_base::in); // Move buffer position back to beginning.
char * buffer = new char[fbuff_size]; // Buffer to store file data.
ptr_fbuff->sgetn(buffer, fbuff_size); // Get file data.
Second way:
std::stringstream sstm_buffer; // Buffer to file contents.
sstm_buffer << ifs.rdbuf(); // Read file contents to sstm.
const std::string & str_buffer = sstm_buffer.str(); // Get underlying string from sstm.
char * buffer = new char[str_buffer.size()]; // Buffer to store file data.
str_buffer.copy(buffer, str_buffer.size()); // Copy file contents to buffer.
Do stuff:
GumboOutput * ptr_outpt = gumbo_parse(buffer);
//...
Close file:
gumbo_destroy_output(&kGumboDefaultOptions, ptr_outpt);
ifs.close(); // Close stream to file.
delete[] buffer; // Delete allocated buffer.
What are the differences between the two in terms of memory cost and speed. Clearly one uses a Stringstream as a buffer before putting the contents into the C-style string, and the other uses a filebuf before putting the contents into a C-style string.
Now to my second question. Ownership semantics and memory allocation. Does the ifstream allocate any memory in the heap for the buffer returned from rdbuf? Am I responsible for deleting the buffer returned from rdbuf? If it doesn't, say I'm reading a huge file... isn't that potentially a LOT of data to be storing in the stack?
Edit:
std::unique_ptr<std::string> mytype::my_func(const std::string & path)
{
std::ifstream ifs(path); // Input file stream
std::stringstream sstm_buffer; // Buffer to file contents.
sstm_buffer << ifs.rdbuf(); // Read file contents to sstm.
ifs.close(); // Close stream to file.
auto ptr_buffer = std::make_unique<std::string>(sstm_buffer.str()); // Pointer to copy of sstm buffer contents.
return std::move(ptr_buffer); // Return pointer.
}
Edit2:
std::string mytype::my_func(const std::string & path) const
{
std::ifstream ifs(path);
std::stringstream sstm_buf;
sstm_buf << ifs.rdbuf();
ifs.close();
return sstm_buf.str();
}
Edit3:
std::string psclient::file_get(const std::string & path) const
{
std::ifstream ifs(path); // Stream to file (Automatically close() on ~).
std::ostringstream reader; // Stream to read file contents.
reader << ifs.rdbuf(); // Read in file contents.
return reader.str(); // Return a move instead of copy (Done implicitly).
}