转载请注明:

仰望高端玩家的小清新 http://www.cnblogs.com/luruiyuan/

C语言可以获得接近汇编的性能,而输入输出常常是最为耗时的过程,因此可以使用 C 语言中的 fread 和 fwrite 来获得最高的读写性能。

例如,可以将其写在源码文件中直接使用:不建议使用这种方式,并且FastIO.cpp代码中有几个bug,懒得改了。直接用FastIO.h即可,这里的改过bug了。

  1 #include <cstdio> // EOF 的定义
  2 #include <cassert> // assert 函数定义
  3 #include <sys/stat.h> // 读取文件状态
  4
  5 /**
  6  * 快速输入输出模板
  7  * 使用 fread 和 fwrite 获得高于 scanf 和 printf 的文件 I/O 性能
  8  */
  9 namespace FastIO {
 10
 11     // 快速输入
 12     namespace in{
 13         const int inputBuffSize = 67108864; // 输入缓冲区大小 64MB
 14         char buff[inputBuffSize], *ptr = NULL, *pend = NULL;
 15         FILE *stream = NULL;
 16         int filesize, readsize, itemsize, maxcnt, maxbytes; // 文件大小字节数, 已读字节数
 17
 18         // 指定文件路径, 并根据文件头获取文件大小
 19         inline int getsize(const char *path){
 20             struct stat statbuff;
 21             stat(path, &statbuff);
 22             return statbuff.st_size;
 23         }
 24
 25         /* 初始化 Fast in 参数
 26          *      (const char*) path: 文件路径
 27          *      (const char*) mode: 文件打开模式
 28          *   (const int) element_size=1: 文件读取的块大小, 默认为 1 字节, 缓冲区大小为 64M
 29          */
 30         inline void init(const char *path, const char *mode="rb", const int element_size=1){
 31             assert((stream == NULL) && (stream = fopen(path, mode)) != NULL);
 32             filesize = getsize(path);
 33             readsize = 0;
 34             itemsize = element_size;
 35             maxcnt = inputBuffSize / element_size; // buffer 整块读取时可容纳的最大块数
 36             maxbytes = (inputBuffSize / element_size) * element_size; // buffer 整块读取时可容纳的最大字节数
 37             ptr = pend = NULL;
 38         }
 39
 40         /**
 41          * 读取流 stream 中的下一个字符, 当缓冲区内容读取完毕后进行下一次I/O
 42          * 返回EOF(-1)表示读取完成, 返回-2表示达到文件尾之前出错
 43          */
 44         inline char nextchar(){
 45             if (readsize >= filesize) return EOF; // 文件读取完成
 46             if (ptr >= pend){
 47                 int realbytes = itemsize * fread(buff, itemsize, maxcnt, stream); // fread返回实际读取的块数
 48                 if (realbytes < maxbytes && realbytes + readsize < filesize) return -2; // 读取出错 返回-2
 49                 ptr = buff; // 重置首尾指针
 50                 pend = buff + realbytes;
 51             }
 52             return readsize++, *ptr++;
 53         }
 54
 55         // 读取一个整数, true 表示读取成功, false 表示读取失败
 56         inline bool read(int &x){
 57             char c = nextchar();
 58             while (c >= 0 && c != '-' && (c < '0' || c > '9')) c = nextchar();
 59             if (c < 0) return false; // c == -1 (EOF): 到达文件尾, c == -2: 读取出错
 60             int sign = (c == '-') ? -1 : 1; // 正负号
 61             x = (c == '-') ? 0 : c - '0';
 62             while (c = nextchar(), c >= '0' && c <= '9') x = x * 10 + c - '0';
 63             x *= sign;
 64             return true;
 65         }
 66
 67         // 读取一个长度为 n 的整数 tuple, 如 (1, -2, 31), true 表示读取成功, false 表示失败
 68         inline bool read(int *p, const int n){
 69             for (int *end = p + n; p < end; ++p) if (!read(*p)) return false;
 70             return true;
 71         }
 72
 73         // 关闭输入流释放资源
 74         inline int close(){
 75             int ret = fclose(stream);
 76             filesize = readsize = itemsize = maxcnt = 0;
 77             ptr = pend = NULL;
 78             stream = NULL;
 79             return ret;
 80         }
 81     }
 82
 83     // 快速输出
 84     namespace out{
 85         const int outputBuffSize = 67108864; // 输出缓冲区大小 64MB
 86         char buff[outputBuffSize], *ptr = NULL, *pend = NULL;
 87         FILE *stream = NULL;
 88         int itemsize, maxbytes; // 写入的块大小, 整块存放时缓存的最大字节数
 89
 90         inline void init(const char *path, const char *mode="wb", const int element_size=1){
 91             assert(stream == NULL && (stream = fopen(path, mode)) != NULL);
 92             itemsize = element_size;
 93             maxbytes = (outputBuffSize / element_size) * element_size; // 输出缓冲的最大字节数
 94             ptr = buff;
 95             pend = buff + maxbytes;
 96         }
 97
 98         // 冲刷缓冲区
 99         inline void flush(){
100             fwrite(buff, itemsize, (ptr - buff) / itemsize, stream);
101             ptr = buff; // 调整首指针
102             fflush(stream);
103         }
104
105         // 写入一个字符到文件中
106         inline void write(const char &c){
107             if (ptr >= pend) flush();
108             *ptr++ = c;
109         }
110
111         // 写一个字符串到文件中
112         inline void write(const char *s){
113             for(; *s; ++s) write(*s); // 读取到字符串尾部时 '\0' ASCII为0
114         }
115
116         // 写入一个整数到文件中
117         inline void write(int x){
118             char buf[20], *p = buf;
119             if (x == 0) write('0');
120             if (x < 0) write('-'), x = -x;
121             while (x > 0) *p++ = x % 10 + '0', x /= 10;
122             while (p > buf) write(*--p);
123         }
124
125         // 写入一个整型tuple到文件中 如 (32, -1, 14), drop_end 控制是否输出 end 符号
126         inline void write(const int *p, const int n, const char *left="(", const char *right=")",
127                           const char *split=", ", const char *end="\n", const bool drop_end=false){
128             write(left);
129             for (const int *ptrend = p + n - 1; p < ptrend; ++p){
130                 write(*p);
131                 write(split);
132             }
133             write(*++p);
134             write(right);
135             if (!drop_end) write(end);
136         }
137
138         // 冲刷缓冲并关闭输出流释放资源
139         inline int close(){
140             if (ptr > buff) flush();
141             int ret = fclose(stream);
142             ptr = pend = NULL;
143             stream = NULL;
144             return ret;
145         }
146     }
147 }

FastIO.cpp

由于内联函数可以写入到头文件中,因此可以将FastIO的实现放入 FastIO.h 中,然后在调用时通过 include 包含即可,FastIO.h 如下,其中包含了对于string类型的支持:强烈建议使用这种方式

  1 #pragma once
  2 #include <cstdio> // EOF 的定义
  3 #include <string> // string 类型的支持
  4 #include <cassert> // assert 函数定义
  5 #include <sys/stat.h> // 读取文件状态
  6 #include <vector> // 读写vector
  7
  8 #define inputBuffSize (67108864) // 输入缓冲区大小 64MB
  9 #define outputBuffSize (67108864) // 输入缓冲区大小 64MB
 10
 11 namespace FastIO { // 由于头文件中可以定义内联函数, 因此将FastIO定义在头文件中便于使用
 12     // 快速输入
 13     namespace in{
 14         char buff[inputBuffSize], *ptr = NULL, *pend = NULL;
 15         FILE *stream = NULL;
 16         int filesize, readsize, itemsize, maxcnt, maxbytes; // 文件大小字节数, 已读字节数
 17
 18         // 指定文件路径, 并根据文件头获取文件大小
 19         inline int getsize(const char *path){
 20             struct stat statbuff;
 21             stat(path, &statbuff);
 22             return statbuff.st_size;
 23         }
 24
 25         // 初始化 Fast in 参数
 26         //      (const char*) path: 文件路径
 27         //      (const char*) mode: 文件打开模式
 28         //   (const int) element_size=1: 文件读取的块大小, 默认为 1 字节, 缓冲区大小为 64M
 29         inline void init(const char *path, const char *mode="rb", const int element_size=1){
 30             assert((stream == NULL) && (stream = fopen(path, mode)) != NULL);
 31             filesize = getsize(path);
 32             readsize = 0;
 33             itemsize = element_size;
 34             maxcnt = inputBuffSize / element_size; // buffer 整块读取时可容纳的最大块数
 35             maxbytes = (inputBuffSize / element_size) * element_size; // buffer 整块读取时可容纳的最大字节数
 36             ptr = pend = NULL;
 37         }
 38
 39         // 初始化 Fast in 参数
 40         //      (const string) path: 文件路径
 41         //      (const char*) mode: 文件打开模式
 42         //   (const int) element_size=1: 文件读取的块大小, 默认为 1 字节, 缓冲区大小为 64M
 43         inline void init(const std::string &path, const char *mode="rb", const int element_size=1){
 44             init(path.c_str(), mode, element_size);
 45         }
 46
 47         // 读取流 stream 中的下一个字符, 当缓冲区内容读取完毕后进行下一次I/O
 48         // 返回EOF(-1)表示读取完成, 返回-2表示达到文件尾之前出错
 49         inline char nextchar(){
 50             if (readsize >= filesize) return EOF; // 文件读取完成
 51             if (ptr >= pend){
 52                 int realbytes = itemsize * fread(buff, itemsize, maxcnt, stream); // fread返回实际读取的块数
 53                 if (realbytes < maxbytes && realbytes + readsize < filesize) return -2; // 读取出错 返回-2
 54                 ptr = buff; // 重置首尾指针
 55                 pend = buff + realbytes;
 56             }
 57             return readsize++, *ptr++;
 58         }
 59
 60         // 读取一个字符, 读取失败则不改变char, 否则改变char c的值
 61         inline bool read(char &c){
 62             char tmp = nextchar(); // tmp == -1 (EOF): 到达文件尾, tmp == -2: 读取出错
 63             return tmp < 0 ? false : (c = tmp, true);
 64         }
 65
 66         // 读取一个整数, true 表示读取成功, false 表示读取失败
 67         inline bool read(int &x){
 68             char c = nextchar();
 69             while (c >= 0 && c != '-' && (c < '0' || c > '9')) c = nextchar();
 70             if (c < 0) return false; // c == -1 (EOF): 到达文件尾, c == -2: 读取出错
 71             int sign = (c == '-') ? -1 : 1; // 正负号
 72             x = (c == '-') ? 0 : c - '0';
 73             while (c = nextchar(), c >= '0' && c <= '9') x = x * 10 + c - '0';
 74             x *= sign;
 75             return true;
 76         }
 77
 78         // 读取一个长度为 n 的整数 tuple, 如 (1, -2, 31), true 表示读取成功, false 表示失败
 79         inline bool read(int *p, const int n){
 80             for (int *end = p + n; p < end; ++p) if (!read(*p)) return false;
 81             return true;
 82         }
 83
 84         // 关闭输入流释放资源
 85         inline int close(){
 86             int ret = fclose(stream);
 87             filesize = readsize = itemsize = maxcnt = 0;
 88             ptr = pend = NULL;
 89             stream = NULL;
 90             return ret;
 91         }
 92     }
 93
 94     // 快速输出
 95     namespace out{
 96         char buff[outputBuffSize], *ptr = NULL, *pend = NULL;
 97         FILE *stream = NULL;
 98         int itemsize, maxbytes; // 写入的块大小, 整块存放时缓存的最大字节数
 99
100         // 初始化 Fast out 参数
101         //      (const char*) path: 文件路径
102         //      (const char*) mode: 文件打开模式
103         //   (const int) element_size=1: 文件读取的块大小, 默认为 1 字节, 缓冲区大小为 64M
104         inline void init(const char *path, const char *mode="wb", const int element_size=1){
105             assert(stream == NULL && (stream = fopen(path, mode)) != NULL);
106             itemsize = element_size;
107             maxbytes = (outputBuffSize / element_size) * element_size; // 输出缓冲的最大字节数
108             ptr = buff;
109             pend = buff + maxbytes;
110         }
111
112         // 初始化 Fast out 参数
113         //      (const string) path: 文件路径
114         //      (const char*) mode: 文件打开模式
115         //   (const int) element_size=1: 文件读取的块大小, 默认为 1 字节, 缓冲区大小为 64M
116         inline void init(const std::string &path, const char *mode="wb", const int element_size=1){
117             init(path.c_str(), mode, element_size);
118         }
119
120         // 冲刷缓冲区
121         inline void flush(){
122             fwrite(buff, itemsize, (ptr - buff) / itemsize, stream);
123             ptr = buff; // 调整首指针
124             fflush(stream);
125         }
126
127         // 写入一个字符到文件中
128         inline void write(const char &c){
129             if (ptr >= pend) flush();
130             *ptr++ = c;
131         }
132
133         // 写一个字符串到文件中
134         inline void write(const char *s){
135             for(; *s; ++s) write(*s); // 读取到字符串尾部时 '\0' ASCII为0
136         }
137
138         // 写一个 string 类型的字符串到文件中
139         inline void write(const std::string &s){
140             write(s.c_str());
141         }
142
143         // 写入一个整数到文件中
144         inline void write(int x){
145             char buf[20], *p = buf;
146             if (x == 0) write('0');
147             if (x < 0) write('-'), x = -x;
148             while (x > 0) *p++ = x % 10 + '0', x /= 10;
149             while (p > buf) write(*--p);
150         }
151
152         template<typename T>
153         // 写入一个含有n个元素的tuple到文件中 如 (32, -1, 14), drop_end 控制是否输出 end 符号
154         inline void write(const T *p, int n, const char *left="(", const char *right=")",
155                           const char *split=", ", const char *end="\n", const bool drop_end=false){
156             write(left);
157             while (--n) write(*p++), write(split);
158             write(*p);
159             write(right);
160             if (!drop_end) write(end);
161         }
162
163         template<typename T>
164         // 写入一个使用 vector 存储的 tuple
165         inline void write(std::vector<T> &vec, const char *left="(", const char *right=")",
166                           const char *split=", ", const char *end="\n", const bool drop_end=false){
167             int n = vec.size() - 1;
168             write(left);
169             for (int i = 0; i < n; ++i) write(vec[i]), write(split);
170             write(vec[n]);
171             write(right);
172             if (!drop_end) write(end);
173         }
174
175         // 冲刷缓冲并关闭输出流释放资源
176         inline int close(){
177             if (ptr > buff) flush();
178             int ret = fclose(stream);
179             ptr = pend = NULL;
180             stream = NULL;
181             return ret;
182         }
183     }
184 }

FastIO.h

调用时,只需将头文件 FastIO.h 引入,然后使用其命名空间 FastIO::in, FastIO::out

简单的使用方式如下,这里假定了 main.cpp 和 FastIO.h 在同一个目录下:(如果不在,需要用相对路径)

 1 // 在 main.cpp 中引入FastIO.h 和 命名空间 FastIO 即可
 2
 3 #include"FastIO.h"
 4 using namespace FastIO;
 5
 6 int main(int argc, char *argv[]){
 7     int buff[10];
 8     // 初始化写入文件流
 9     out::init("out.txt", "wb");
10     // 测试5个数一组的tuple读取和写入
11     in::init("in.txt", "rb");
12     while(in::read(buff, 5)) out::write(buff, 5);
13     // 释放读文件资源
14     in::close();
15     // 释放写文件资源,冲刷缓冲区
16     out::close();
17 }

转载于:https://www.cnblogs.com/luruiyuan/p/10518374.html

C++快速文件输入输出相关推荐

  1. c++语言文件流,C++ IO类、文件输入输出、string流详细讲解

    新的C++标准中有三分之二的内容都是描述标准库.接下来重点学习其中几种核心库设施,这些是应该熟练掌握的. 标准库的核心是很多容器类(顺序容器和关联容器等)和一簇泛型算法(该类算法通常在顺序容器一定范围 ...

  2. python 学习笔记 5 -- 文件输入输出

    本文主要介绍python下的文件输入输出操作,python的文件操作简单易用-通过本文相信你可以熟练掌握file和pickle这两种输入输出操作! 1.文件 你可以通过创建一个file类的对象来打开一 ...

  3. python 中文件输入输出及os模块对文件系统的操作

    整理了一下python 中文件的输入输出及主要介绍一些os模块中对文件系统的操作. 文件输入输出 1.内建函数open(file_name,文件打开模式,通用换行符支持),打开文件返回文件对象. 2. ...

  4. OpenCV文件输入输出的序列化功能的实例(附完整代码)

    OpenCV文件输入输出的序列化功能的实例 OpenCV文件输入输出的序列化功能的实例 OpenCV文件输入输出的序列化功能的实例 #include <opencv2/core.hpp> ...

  5. Kettle使用_11 CSV文件输入输出复制数量

    Kettle使用_11 CSV文件输入输出复制数量 需求: 通过并行方式完成customers-100.txt(该文件有2.4万条记录)的文本输出. 解决方法:结合CSV文本输入和文件文本输出组件解决 ...

  6. C++primer第八章 IO库 8.2 文件输入输出

    8.2文件输入输出 头文件fstream定义了三个类型来支持文件IO:ifstream从一个给定文件读取数据,ofstream向一个给定文件写入数据,以及fstream可以读写给定文件.在17.5.3 ...

  7. C ++基础 | 格式化输出,文件输入输出(File IO),头文件(Header Files)_3

    目录 格式化输出 文件输入输出(File IO) 头文件(Header Files) 格式化输出 要格式化数据,我们可以使用转义字符串(Escape Sequence)也称字符实体(Character ...

  8. 快速文件扫描王用户协议

    用户协议 1.导言 欢迎您使用" 快速文件扫描王"软件及相关服务! " 快速文件扫描王 "软件及相关服务,系指北京爱尚苹果信息科技有限公司及其关联方(以下简称& ...

  9. [避坑] C/C++ 如何实现文件输入输出

    请看完后点个赞,谢谢 说起 CSP-J(NOIP普及).CSP- S (NOIP提高).NOIP等等考试,大家应该印象最深的就是文件输入输出了吧,很多考生就是因为这个爆零的. 先说说CCF评测答案的方 ...

最新文章

  1. lambda^k/k! 积分
  2. 2020年 HackerEarth 调查:Go 语言成为最受欢迎的语言 开发者最关心职业发展路径...
  3. SAP Spartacus 的 Above-the-Fold Loading 加载机制
  4. 两个栈实现队列与两个队列实现栈
  5. Spring Boot笔记-自动配置(Spring Boot封装成jar被其他项目引用)
  6. MFC开发IM-第十九篇、获取编辑框内容,并且追加内容
  7. jmeter - 录制app接口
  8. 微信小程序调查报告(一)
  9. 我国祖冲之密码算法ZUC128和ZUC256性能测试
  10. 比特大陆将任命新任首席执行官
  11. Unity获取物体下的子物体+只获取子物体
  12. SSR、SSE、SST、判定系数(可决系数、拟合优度)的计算公式
  13. 1星《微信软文营销实战技巧》:标题党,作者没有实战经验
  14. Unity3D网络游戏0.2
  15. vos3000外呼系统话机或网关注册掉线或未注册怎样解决
  16. 光纤收发器怎么使用?
  17. 《大型数据库技术,传智播客Java百度网盘
  18. Spring Security系列教程18--会话管理之防御固定会话攻击
  19. 基于JAVA企业进销管理系统的设计与实现计算机毕业设计源码+数据库+lw文档+系统+部署
  20. 达梦的异构数据库同步软件DMHS的简单安装

热门文章

  1. 基于Keras实现Kaggle2013--Dogs vs. Cats12500张猫狗图像的精准分类
  2. 第一章 电商秒杀商品回顾
  3. 收藏一个开源.netCMS项目
  4. 组合预测模型 | ARIMA-LSTM时间序列预测(Python)
  5. 机器学习十大算法汇总
  6. Appium Server源码分析之作为Bootstrap客户端
  7. 【优化求解】基于花朵授粉FPA算法求解最优目标matlab代码
  8. 上海杭州北京重庆深圳等JAVA职位(8月12)
  9. LED发光二极管限流电阻的选择-点亮LED灯泡-发光二极管-限流电阻
  10. 渣打银行:中国人口数量或见顶 工资水平存在明显上涨趋势