Search code examples
c++boostboost-iostreams

Copying file content to a container not type of char?


I have an disrupive issue with my code. I'm using boost iostreams library to copy file content to a vector which is provided by other component of a system thus I'm unable to change type of this container. I have solved this problem by creating a temporal container which is char type and I'll make copy of the content to the target container from this. However I'm wondering would it be possible to solve the problem without temporal containers?

Consider following code.

namespace io = boost::iostreams;
namespace fs = boost::filesystem;

std::vector<char> container;
std::vector<unsigned char> anotherContainer;

auto inputFile = io::file_descriptor_source(fs::path(L"testfile.txt"));

auto inserter = io::back_inserter(container);
auto anotherInserter = io::back_inserter(anotherContainer);

io::copy(inputFile, inserter);
io::copy(inputFile, anotherInserter);

The code is not valid to compile itself, just provided by an example.

Question: How do I make latter copy function call

io::copy(inputFile, anotherInserter);

to compile in following scenario? Can I write a filter which provides the type conversion?


Solution

  • You can create an std::istream from io::file_descriptor_source and then read chars into a vector using its range constructor:

    template<class IoDevice>
    std::vector<unsigned char> read_all(IoDevice& io_device) {
        boost::iostreams::stream<IoDevice> io_stream(io_device);
        return std::vector<unsigned char>(
              std::istreambuf_iterator<char>{io_stream}
            , std::istreambuf_iterator<char>{}
            );
    }
    
    int main() {
        namespace io = boost::iostreams;
        namespace fs = boost::filesystem;
        auto inputFile = io::file_descriptor_source(fs::path(L"testfile.txt"));
        auto anotherContainer = read_all(inputFile);
    }
    

    Be careful with this method of unconditionally reading entire files though, because a malicious user could direct it to read /dev/zero causing your application to keep reading until it runs out of memory.