在cpp中使用boost::asio以非阻塞异步方式读取文件内容

问题描述 投票:0回答:1

我有类似的问题boost:asio文件读取

boot::asio 是否支持异步读取功能中从文件系统读取常规文件?

我尝试了下面的代码,但它似乎不起作用。

#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;
}

我可以看到我的handleRead被调用,但bytesRead始终为1024,无论文件大小如何。该文件只有几个字节的数据。

c++ asynchronous boost-asio
1个回答
2
投票

是的,可以。

您的代码已经可以工作了,请查看它Live On Coliru (简化版

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

打印

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

现代亚洲

请注意,最近 Asio(1.22.0 或 Boost 1.78)获得了文件支持。它还具有随机访问支持,并将在各种平台上使用更优化的接口(例如 Windows 完成端口和 Linux 上的 io_uring)。请参阅文件和管道。演示:

#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";
}

请注意,这里的工作防护实际上是多余的,但我想展示如何更优雅地编写它,以防您有时以使其不冗余的方式移动事物。

© www.soinside.com 2019 - 2024. All rights reserved.