0

I know there is boost:filesystem::copy_file which allows copying the whole file. But I need to copy part of file from the beginning to some specific offset to other file. My question is if there is anything in the boost to do that?

If not then it seems I need to use fopen/fread/fwrite and implement my own custom copying loop.

Update: I don't ask for most effective way to copy a file. I don't mention Linux. I wonder how this question can be seen as a duplicate of the "most efficient way to copy file on Linux" question. It looks like all those people marking it as duplicate didn't read my question at all.

igor.sol
  • 627
  • 7
  • 18
  • 2
    I don't think there would be since I'm not aware any OS have this function. – apple apple Sep 25 '18 at 11:48
  • this question is at the edge of asking to recommend or find tool or software library, which is off-topic. Maybe instead of asking to find "anything" show your attempt and ask how to do it with less boilerplate – 463035818_is_not_an_ai Sep 25 '18 at 12:07
  • I would use boost::multiprocess to memory map the first file. Then open the second file and write it using posix file descriptors. – Richard Hodges Sep 25 '18 at 12:08

2 Answers2

1

The most efficient boost route would I think be a memory mapped file for the source file and a direct write for the destination file.

This program takes 2 filename arguments. It copies the first half of the source file to the destination file.

#include <boost/iostreams/device/mapped_file.hpp>
#include <iostream>
#include <fstream>
#include <cstdio>

namespace iostreams = boost::iostreams;
int main(int argc, char** argv)
{
    if (argc != 3)
    {
        std::cerr << "usage: " << argv[0] << " <infile> <outfile> - copies half of the infile to outfile" << std::endl;
        std::exit(100);
    }

    auto source = iostreams::mapped_file_source(argv[1]);
    auto dest = std::ofstream(argv[2], std::ios::binary);
    dest.exceptions(std::ios::failbit | std::ios::badbit);
    auto first = source. begin();
    auto bytes = source.size() / 2;
    dest.write(first, bytes);
}

As per comments, depending on OS, your mileage may vary with system calls such as splice and sendfile, however note the comments in the man page:

Applications may wish to fall back to read(2)/write(2) in the case where sendfile() fails with EINVAL or ENOSYS.

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • 2
    Most efficient? [`splice`](https://linux.die.net/man/2/splice) wants to have a word :) Because the pages never leave kernel space, they might not even need mapping to the process space - depending perhaps on the presence of DMA aware controllers, – sehe Sep 25 '18 at 12:52
  • @sehe wow! I never knew such a thing existed. I'll add it to my latest pet project: https://gitlab.com/madmongo1/wrapper – Richard Hodges Sep 25 '18 at 13:20
  • 1
    @sehe thanks. It seems splice requires "one of the descriptors must refer to a pipe" but sendfile should work. – igor.sol Sep 25 '18 at 14:18
1

If not then it seems I need to use fopen/fread/fwrite and implement my own custom copying loop.

Just to illustrate that there is a vanilla solution between Boost and C.

#include <fstream>
#include <algorithm>
#include <iterator>

int main()
{
    std::ifstream fin("in",std::ios_base::binary);
    fin.exceptions(std::ios::failbit | std::ios::badbit);
    std::ofstream fout("out",std::ios_base::binary);
    fout.exceptions(std::ios::failbit | std::ios::badbit);
    std::istream_iterator<char> iit(fin);
    std::ostream_iterator<char> oit(fout);
    std::copy_n(iit,42,oit);
    return 0;
}

Exception-handling TODO.

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182