Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

原始文件

asco::io::file 提供直接面向操作系统的文件读写接口(不进行用户态缓冲),基于协程的异步 API,适合需要精确控制 I/O 的场景。

要点

  • 无用户态缓冲:请求直接提交到内核
  • 异步接口:open/close/reopen/write/read 均为协程;read 可被打断并恢复,open/close/reopen/write 为不可打断的 inline future
  • 独立读写指针:支持 seekg/seekp 与 tellg/tellp
  • 可取得原生句柄以与其他系统 API 协作
  • 与零拷贝缓冲区 buffer<> 协同良好

主要类型

  • file:已打开文件的句柄
  • file::options:打开选项(位标志)
  • opener:链式配置的打开器(builder)
  • open_file:底层打开实现(返回 future<std::expected<file,int>>
  • read_result:读取结果状态(eof/interrupted/again
  • file_state:文件状态视图(如 size()

打开与关闭

创建打开器

  • file::at(path):基于路径创建 opener
  • file::at():从现有 file 的上下文创建 opener(便于 reopen()

打开/关闭方法

  • future_inline<void> open(std::string path, flags<file::options> opts, uint64_t perm = 0)
  • future<void> close()
  • future_inline<void> reopen(opener&&)

注意

  • 已打开对象再次 open() 将抛出异常
  • 使用 create 选项时应提供 perm(如 0644)
  • 析构时若仍处于打开状态将自动 close()

示例

using asco::io::file;
using asco::flags;

auto r = co_await file::at("/tmp/data.log")
             .write().append().create().exclusive()
             .mode(0644)
             .open();
if (!r) co_return;                // r.error() 为 errno
file f = std::move(*r);

// 或:file f; co_await f.open("/tmp/data.log", flags{file::options::write}, 0644);
co_await f.close();

读写

写入

  • 签名:future<std::optional<buffer<>>> write(buffer<> buf)(不可中止)
  • 语义:尽量写出 buf,未全部写完则返回剩余数据;全部写尽返回 std::nullopt
  • 需以 options::write 打开

读取

  • 签名:future<std::expected<buffer<>, read_result>> read(size_t nbytes)
  • 语义:读取至多 nbytes,成功返回数据,否则返回 eof/interrupted/again
  • 需以 options::read 打开(可被中止)

示例:写到完成

asco::io::buffer<> buf("hello");
while (true) {
    auto rest = co_await f.write(std::move(buf));
    if (!rest) break;
    buf = std::move(*rest);
}

示例:读到 EOF

std::string out;
for (;;) {
    auto r = co_await f.read(4096);
    if (!r) {
        if (r.error() == asco::io::read_result::eof) break;
        if (r.error() == asco::io::read_result::interrupted) continue;
        if (r.error() == asco::io::read_result::again) { co_await std::suspend_always{}; continue; }
    } else {
        out += std::move(*r).to_string();
    }
}

指针与状态

  • size_t seekg(ssize_t offset, seekpos whence = seekpos::current)
  • size_t seekp(ssize_t offset, seekpos whence = seekpos::current)
  • size_t tellg() const
  • size_t tellp() const
  • file_state state() const(Linux:基于 fstat()

说明

  • seekpos::beginoffset 必须非负
  • seekpos::endoffset 必须非正
  • seekpos::current:允许正负偏移,但不得越界
  • 越界将抛出运行时错误

示例

f.seekp(0, asco::io::seekpos::end); // 追加写
auto pos = f.tellp();
f.seekg(0, asco::io::seekpos::begin);

原生句柄

  • raw_handle():返回底层原生句柄(Linux 为 int),可与系统 API 协作