2

I have question similar to this boost:asio file read.

does boot::asio support reading regular file from file system in async read function ?

I tried below code but it does not seem to work.

#include <iostream>
#include <fstream>
#include <boost/asio.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>

void handleRead(const boost::system::error_code& error, std::size_t bytesRead) {
    if (!error) {
        // Process the read data here
        std::cout << "Read " << bytesRead << " bytes" << std::endl;
    } else {
        std::cerr << "Error: " << error.message() << std::endl;
    }
}

int main() {
    boost::asio::io_context ioContext;
    boost::asio::executor_work_guard<boost::asio::io_context::executor_type> workGuard(ioContext.get_executor());

    const char* filename = "example.txt";

    // Open the file
    int fileDescriptor = open(filename, O_RDONLY);
    if (fileDescriptor == -1) {
        std::cerr << "Failed to open file: " << filename << std::endl;
        return 1;
    }

    // Wrap the file descriptor with a stream_descriptor
    boost::asio::posix::stream_descriptor file(ioContext, fileDescriptor);

    // Create a buffer to hold the file data
    const std::size_t bufferSize = 1024;
    std::vector<char> buffer(bufferSize);

    // Read the file asynchronously
    boost::asio::async_read(file, boost::asio::buffer(buffer),
        boost::asio::transfer_at_least(1),
        boost::bind(&handleRead, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

    // Run the I/O service
    ioContext.run();

    return 0;
}

I can see my handleRead being called but the bytesRead coming as 1024 always irrespective of file size. The file has only few bytes of data.

Rohit Pai
  • 89
  • 9

1 Answers1

1

Yes, you can.

Your code already works, see it Live On Coliru (simplified)

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp 
./a.out
touch example.txt;            ./a.out
echo -n 'abc' >> example.txt; ./a.out
echo -n 'def' >> example.txt; ./a.out

Prints

Failed to open file: example.txt
End of file: 0 bytes
Success: 3 bytes
Success: 6 bytes

Modern Asio

Note that more recently Asio (1.22.0 or Boost 1.78) got file support. It also has random access support and will use more optimal interfaces on various platforms (e.g. Windows completion ports and io_uring on Linux). See Files And Pipes. Demo:

#define BOOST_ASIO_HAS_IO_URING 1 // on linux
#include <boost/asio.hpp>
#include <boost/asio/stream_file.hpp>
#include <iostream>

namespace asio = boost::asio;

void handleRead(boost::system::error_code ec, size_t n) {
    std::cout << ec.message() << ": " << n << " bytes" << std::endl;
}

int main(int argc, char** argv) try {
    asio::io_context ioc;

    auto work     = make_work_guard(ioc);
    auto filename = argc > 1 ? argv[1] : "example.txt";

    // Open the file
    using asio::stream_file;
    stream_file file(ioc, filename, stream_file::flags::read_only);

    // Create a buffer to hold the file data
    size_t            bufferSize = 1024;
    std::vector<char> buffer(bufferSize);

    // Read the file asynchronously
    async_read(file, asio::buffer(buffer), asio::transfer_at_least(1), handleRead);

    // Run the I/O service
    work.reset();
    ioc.run();
} catch (boost::system::system_error const& se) {
    std::cerr << "Error: " << se.code().message() << "\n";
}

enter image description here

sehe
  • 374,641
  • 47
  • 450
  • 633