欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > 2407C++,跨平台读写文件

2407C++,跨平台读写文件

2025/9/22 11:49:33 来源:https://blog.csdn.net/fqbqrr/article/details/140241649  浏览:    关键词:2407C++,跨平台读写文件

原文

C++文件操作这一块比较混乱,可用std::fstream去读写文件,也可用fread/fwrite去读写文件,linux平台上还可用pread/pwrite去读写文件.

除此外,linux平台还可io_uring去读写文件,窗口平台则iocp去读写文件.

这些文件操作的api各不相同,有时不知道选择哪个接口更好,如果有一个统一的文件操作接口那就好了,统一的api去操作文件,操作方式包括上述这些读写方式.

如何设计一个统一的文件操作库

文件操作读写方式上分类可分为两类,一个是顺序读写,一个是随机读写,清理一下这些文件操作方式:

文件顺序读写:

fstream.read/write;
fread/fwrite;

linux,io_uring顺序读写;
窗口,iocp顺序读写

文件随机读写:

windows ReadFile/WriteFile;
linux pread/pwrite;

linux,io_uring随机读写;
窗口,iocp随机读写

再从另外一个维度分类,同步读写和异步读写:

同步读写:

fstream.read/write;
2.fread/fwrite;
windows ReadFile/WriteFile;
2.linux pread/pwrite;

异步读写:

linux,io_uring读写;
窗口,iocp读写

统一起来似乎有点麻烦.可这样分类,无论是异步还是同步,读写本质都从属于顺序读写随机读写,因此可这样抽象:

文件分为两类,一类是顺序读写的文件,另外一类是随机读写的文件,这两类文件都支持同步读写和异步读写.

但是,还有个问题,文件同步操作阻塞当前线程,很多时候不想阻塞,此时可把同步读写文件的任务交给线程池,并提供一个异步读写接口,在C++20中当然是提供协程接口了.

io_uringiocp是提供真正异步文件接口的本地异步,而fstream,fread,pread这些同步接口需要放到线程池中读写文件.

因此可提供一个统一协程读写接口,默认是会使用io_uring/iocp读写文件,也允许用户显式指定线程池方式读写文件.

最终统一的跨平台的文件操作库如下:

enum class execution_type { none, native_async, thread_pool };
template <execution_type execute_type = execution_type::native_async>
class basic_seq_coro_file {
public:async_simple::coro::Lazy<std::pair<std::error_code, size_t>> async_read(char *buf, size_t size);async_simple::coro::Lazy<std::pair<std::error_code, size_t>> async_write(std::string_view buf);
};

顺序文件读写来说,用户只需要定义basic_seq_coro_file时,指定execution_type就可以了,默认为native_async,会通过io_uringiocp异步写文件,如果设置native_asyncthread_pool,则会在线程池中通过std::fstream顺序读写文件.

再来看看随机读写文件的类,也是类似的,只是多了一个偏移:

template <execution_type execute_type = execution_type::native_async>
class basic_random_coro_file {public:async_simple::coro::Lazy<std::pair<std::error_code, size_t>> async_read_at(uint64_t offset, char *buf, size_t size);async_simple::coro::Lazy<std::pair<std::error_code, size_t>> async_write_at(uint64_t offset, std::string_view buf);
};

默认io_uring/iocp异步读写文件,如果指定execute_typethread_pool方式,则会在线程池pread/ReadFile,pwrite/WriteFile随机读写文件.

如果嫌模板类定义太长了,可给个默认别名:

using coro_file = basic_seq_coro_file<>;
using random_coro_file = basic_random_coro_file<>;

这样用起来很方便了:

coro_file顺序读写文件

async_simple::coro::Lazy<void> seq_read(std::string filename) {coro_io::coro_file file{};file.open(filename, std::ios::in);CHECK(file.is_open());std::string str;str.resize(200);{auto pair = co_await file.async_read(str.data(), 10);CHECK(pair.second == 10);CHECK(!file.eof());}{bool ok = file.seek(10, std::ios::beg);CHECK(ok);}{auto pair = co_await file.async_read(str.data(), str.size());CHECK(pair.second == 5);CHECK(file.eof());}
}
async_simple::coro::Lazy<void> seq_write(std::string filename) {coro_io::coro_file file{};//创建一个可读可写的新文件file.open(filename, std::ios::in | std::ios::out | std::ios::trunc);CHECK(file.is_open());std::string str = "hello";co_await file.async_write(str);std::string result;result.resize(10);CHECK(file.seek(0, std::ios::beg));auto [rd_ec, size] = co_await file.async_read(result.data(), 5);std::string_view s(result.data(), size);CHECK(s == "hello");
}

这样默认就会通过io_uring/iocp异步读写文件,如果想在线程池中读写,则这样调用:

void test_seq_read_write(std::string_view filename) {create_files({std::string(filename)}, 190);coro_io::basic_seq_coro_file<coro_io::execution_type::thread_pool> file(filename, std::ios::in | std::ios::out);CHECK(file.is_open());char buf[100];std::error_code ec;size_t size;std::tie(ec, size) = async_simple::coro::syncAwait(file.async_read(buf, 10));CHECK(size == 10);std::string str = "test";std::tie(ec, size) = async_simple::coro::syncAwait(file.async_write(str));CHECK(size == 4);
}

接口简单易用,open接口和std::fstream打开方式一样,seek参数也是一样,免去了重新学习api的负担.

coro_file随机读写文件

void test_random_read_write(std::string_view filename) {create_files({std::string(filename)}, 190);random_coro_fil file(filename, std::ios::in);CHECK(file.is_open());char buf[100];auto pair = async_simple::coro::syncAwait(file.async_read_at(0, buf, 10));CHECK(std::string_view(buf, pair.second) == "AAAAAAAAAA");CHECK(!file.eof());coro_io::basic_random_coro_file<execute_type> file1;file1.open(filename, std::ios::out);CHECK(file1.is_open());std::string buf1 = "cccccccccc";async_simple::coro::syncAwait(file1.async_write_at(0, buf1));std::string buf2 = "dddddddddd";async_simple::coro::syncAwait(file1.async_write_at(10, buf2));
}

coro_file在哪里?它就是yalantinglibs.coro_file:这里

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词