我想做一件简单的事情:读取文件中的第一行,如果没有这样的文件,没有读取文件的权限等等,就做一个适当的错误报告。
我考虑了以下选项:
std::ifstream.不幸的是,没有可移植的方法来报告系统错误。其他一些答案建议在读取失败后检查errno,但标准不保证iostreams库中的任何函数都设置了errno。std::getline的iostreams那么方便。我正在寻找C++解决方案。有没有办法使用C++14和boost来实现这一点?
发布于 2017-08-24 01:40:40
免责声明:我是AFIO的作者。但你要找的正是https://ned14.github.io/afio/,它是v2库,包含了2015年8月Boost同级评审的反馈。See the list of features here。
当然,我要提醒的是,这是一个alpha质量的库,您不应该在生产代码中使用它。然而,已经有相当多的人这样做了。
如何使用AFIO解决OP的问题:
注意,AFIO是一个非常低级的库,因此你必须输入更多的代码来实现与iostream相同的功能,另一方面,你没有内存分配,没有异常抛出,没有不可预测的延迟尖峰:
// Try to read first line from file at path, returning no string if file does not exist,
// throwing exception for any other error
optional<std::string> read_first_line(filesystem::path path)
{
using namespace AFIO_V2_NAMESPACE;
// The result<T> is from WG21 P0762, it looks quite like an `expected<T, std::error_code>` object
// See Outcome v2 at https://ned14.github.io/outcome/ and https://lists.boost.org/boost-announce/2017/06/0510.php
// Open for reading the file at path using a null handle as the base
result<file_handle> _fh = file({}, path);
// If fh represents failure ...
if(!_fh)
{
// Fetch the error code
std::error_code ec = _fh.error();
// Did we fail due to file not found?
// It is *very* important to note that ec contains the *original* error code which could
// be POSIX, or Win32 or NT kernel error code domains. However we can always compare,
// via 100% C++ 11 STL, any error code to a generic error *condition* for equivalence
// So this comparison will work as expected irrespective of original error code.
if(ec == std::errc::no_such_file_or_directory)
{
// Return empty optional
return {};
}
std::cerr << "Opening file " << path << " failed with " << ec.message() << std::endl;
}
// If errored, result<T>.value() throws an error code failure as if `throw std::system_error(fh.error());`
// Otherwise unpack the value containing the valid file_handle
file_handle fh(std::move(_fh.value()));
// Configure the scatter buffers for the read, ideally aligned to a page boundary for DMA
alignas(4096) char buffer[4096];
// There is actually a faster to type shortcut for this, but I thought best to spell it out
file_handle::buffer_type reqs[] = {{buffer, sizeof(buffer)}};
// Do a blocking read from offset 0 possibly filling the scatter buffers passed in
file_handle::io_result<file_handle::buffers_type> _buffers_read = read(fh, {reqs, 0});
if(!_buffers_read)
{
std::error_code ec = _fh.error();
std::cerr << "Reading the file " << path << " failed with " << ec.message() << std::endl;
}
// Same as before, either throw any error or unpack the value returned
file_handle::buffers_type buffers_read(_buffers_read.value());
// Note that buffers returned by AFIO read() may be completely different to buffers submitted
// This lets us skip unnecessary memory copying
// Make a string view of the first buffer returned
string_view v(buffers_read[0].data, buffers_read[0].len);
// Sub view that view with the first line
string_view line(v.substr(0, v.find_first_of('\n')));
// Return a string copying the first line from the file, or all 4096 bytes read if no newline found.
return std::string(line);
}发布于 2019-01-21 05:11:43
boost-users邮件列表上的人指出,boost.beast库具有用于基本文件IO 的独立于操作系统的应用程序接口,包括适当的错误处理。file concept有三种开箱即用的实现: POSIX、stdio和win32。实现支持RAII (销毁时自动关闭)和移动语义。POSIX文件模型自动处理EINTR错误。基本上,这对于可移植地逐块读取文件块以及例如显式地处理缺少文件的情况是足够和方便的:
using namespace boost::beast;
using namespace boost::system;
file f;
error_code ec;
f.open("/path/to/file", file_mode::read, ec);
if(ec == errc::no_such_file_or_directory) {
// ...
} else {
// ...
}发布于 2017-08-24 05:58:45
#include <iostream>
#include <fstream>
#include <string>
#include <system_error>
using namespace std;
int
main()
{
ifstream f("testfile.txt");
if (!f.good()) {
error_code e(errno, system_category());
cerr << e.message();
//...
}
// ...
}ISO C++标准:
报头"cerrno“的内容与POSIX报头"errno.h”相同,不同之处在于errno应定义为宏。注意:其目的是保持与POSIX标准的紧密一致。- end note应为每个线程提供单独的errno值。
https://stackoverflow.com/questions/45840686
复制相似问题