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.
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
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";
}
Note that the work guard is actually redundant here, but I liked to show how I'd write it more elegantly, in case you sometimes move things around in ways that make it not-redundant.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With