我正在使用 Boost.ASIO 读取标准输入,但是当我通过管道输入它时,我希望管道在输入完全消耗时关闭。 IE。我在命令行执行此操作:
cat somefile.txt | myprog
而且我希望 myprog
会看到文件关闭。相反,它会永远等待。
代码如下所示:
boost::asio::posix::stream_descriptor as_stdin(ios);
{
boost::system::error_code error;
as_stdin.assign(dup(STDIN_FILENO), error);
if ( error ) {
exit(2);
}
}
auto proc = [&as_stdinr](auto yield) {
boost::asio::streambuf buffer;
while ( as_stdin.is_open() ) {
auto bytes = boost::asio::async_read_until(as_stdin, buffer, '\n', yield);
if ( bytes ) {
buffer.commit(bytes);
std::istream in(&buffer);
std::string line;
std::getline(in, line);
std::cerr << line << std::endl;
} else {
std::cerr << "No bytes read" << std::endl;
}
}
std::cerr << "Done" << std::endl;
};
boost::asio::spawn(ios, proc);
所有文件内容都被正确回显,因此从管道读取工作正常,但“未读取字节”或“完成”消息都没有被打印出来。我已经尝试过使用和不使用 dup
系统调用。
我是不是误解了管道的工作原理,还是我做错了什么或遗漏了什么?
我认为这归结为“使用协程时如何检测 EOF?”
最佳答案
您可以从 async_read_until 捕获异常
size_t bytes = 0;
bool eof = false;
try {
bytes = boost::asio::async_read_until(as_stdin, buffer, '\n', yield);
} catch(std::exception const& e) {
std::cerr << "Exception: " << e.what() << "\n";
bytes = 0;
eof = true;
}
// ...
if (eof) break;
或者使用错误代码:
boost::system::error_code ec;
auto bytes = boost::asio::async_read_until(as_stdin, buffer, '\n', yield[ec]);
// ...
if (ec) {
std::cerr << "Error: " << ec.message() << "\n";
break;
}
两种情况下的输出非常相似
Exception: End of file
No bytes read
Done
或者
No bytes read
Error: End of file
Done
限制
常规文件不能与 POSIX stream_descriptor 一起使用,参见 https://stackoverflow.com/a/23631715/85371
关于c++ - 使用 Boost.ASIO 读取时标准输入管道未关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40571429/