What I need to do?
I need to read the file from RAM
How I am doing it?
I use std::istream
, because it know how to read from buffer. So, there is method that know how to read file size(according to this SO answer https://stackoverflow.com/a/6039648/5709159)
long getFileSize(const std::string &filename)
{
struct stat stat_buf{};
int rc = stat(filename.c_str(), &stat_buf);
return rc == 0 ? stat_buf.st_size : -1;
}
Then I use membuf to copy bytes from file to buffer (according to this SO answer https://stackoverflow.com/a/13586356/5709159)
struct membuf : std::streambuf
{
membuf(char *base, std::ptrdiff_t n)
{
this->setg(base, base, base + n);
}
};
Full implementation looks like this
long size = getFileSize(filename);
membuf sbuf(0, size);
std::istream file(&sbuf);
But, I am now sure that sbuf(0, size);
that 0
here is on the right place...
So, question is - how to set membuf
with right size ?
Expanding on the code in your question:
long size = getFileSize(filename);
std::vector<char> buffer(size);
// here fill the buffer with data
membuf sbuf(buffer.data(), buffer.size());
std::istream file_from_ram(&sbuf);
if you'd like to fill the buffer with contenst of some file, do this:
std::istream original_file("filename.dat");
original_file.read(buffer.data(), size);
Note: this method has problems. First, as @andrew-henle mentioned in comments, file size of type off_t
which may not fil into long
. Second, this method suffers from TOCTOU (time of check -- time of use) problem: if file size changes between the call to getFileSize and reading the file, you may be in trouble.
Use std::istringstream
instead:
std::string buffer;
// here fill the string with data
std::istringstream file_from_ram(buffer);
If you'd like to fill the buffer with contents of some file, do this (from https://stackoverflow.com/a/116220/4451432):
std::ifstream original_file("filename.dat");
std::istringstream file_from_ram;
file_from_ram << original_file.rdbuf();
// Now you can read from file_from_ram