英文:
reading file contents in non-blocking async way using boost::asio in cpp
问题
我有类似这个boost:asio文件读取的问题。
boost::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) {
// 在这里处理读取的数据
std::cout << "读取 " << bytesRead << " 字节" << std::endl;
} else {
std::cerr << "错误: " << 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";
// 打开文件
int fileDescriptor = open(filename, O_RDONLY);
if (fileDescriptor == -1) {
std::cerr << "无法打开文件: " << filename << std::endl;
return 1;
}
// 使用stream_descriptor包装文件描述符
boost::asio::posix::stream_descriptor file(ioContext, fileDescriptor);
// 创建一个缓冲区来保存文件数据
const std::size_t bufferSize = 1024;
std::vector<char> buffer(bufferSize);
// 异步读取文件
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));
// 运行I/O服务
ioContext.run();
return 0;
}
我可以看到handleRead
被调用,但bytesRead
始终为1024,无论文件大小如何。文件只有几个字节的数据。
英文:
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.
答案1
得分: 1
您可以。
您的代码已经可以正常工作,请查看 在 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
输出:
无法打开文件:example.txt
文件末尾:0 字节
成功:3 字节
成功:6 字节
现代 Asio
请注意,较新的 Asio 版本(1.22.0 或 Boost 1.78)已经支持文件操作。它还具有随机访问支持,并将在各种平台上使用更优化的接口(例如 Windows 完成端口和 Linux 上的 io_uring)。请参阅 Files And Pipes。演示代码如下:
#define BOOST_ASIO_HAS_IO_URING 1 // 在 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";
// 打开文件
using asio::stream_file;
stream_file file(ioc, filename, stream_file::flags::read_only);
// 创建一个缓冲区来保存文件数据
size_t bufferSize = 1024;
std::vector<char> buffer(bufferSize);
// 异步读取文件
async_read(file, asio::buffer(buffer), asio::transfer_at_least(1), handleRead);
// 运行 I/O 服务
work.reset();
ioc.run();
} catch (boost::system::system_error const& se) {
std::cerr << "错误:" << se.code().message() << "\n";
}
英文:
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";
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论