博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ Primer Plus 学习笔记 第十七章 I/O
阅读量:4126 次
发布时间:2019-05-25

本文共 7519 字,大约阅读时间需要 25 分钟。

fstream

写入: ofstream对象  << 或者write()

读取: ifstream对象 >> 或者get()

使用open函数关联文件或者直接用ofstream类型的构造函数来关联文件 没有该文件则会创建该文件

ofstream是ostream的继承类 所以可以使用ostream的所有函数

默认打开方式是截断 也就是清空文件内容

 

程序示例

#include 
#include
#include
int main(){ using namespace std; string filename; cout << "Enter name for new file: "; cin >> filename;// c_str是将字符串转换为C风格的字符串 ofstream fout(filename.c_str()); fout << "For your eyes only!\n"; cout << "Enter your secret number: "; float secret; cin >> secret; fout << "Your secret number is " << secret << endl; fout.close(); ifstream fin(filename.c_str()); cout << "Here are the contents of " << filename << ":\n"; char ch; while (fin.get(ch)) cout << ch; cout << "Done\n"; fin.close(); return 0;}

 

流状态检查和is_open()

文件流状态:

fail() 判断是否试图打开一个不存在的文件 (failbit位)

也可以用is_open()来判断 一样的

使用循环的方式打开一组文件

命令行处理技术

在main()中添加参数

int main(int argc, char *argv[])

argc 参数个数 包括命令名本身

argv指向命令参数的字符数组指针 包括命令名本身

#include 
#include
#include
int main(int argc, char* argv[]){ using namespace std; if (argc == 1) {// [0] 表示的是程序名 cerr << "Usage: " << argv[0] << " filename[s]\n"; exit(EXIT_FAILURE); } ifstream fin; long count; long total = 0; char ch; for (int file = 1; file < argc; file++) { fin.open(argv[file]); if (!fin.is_open()) { cerr << "Could not open " << argv[file] << endl; fin.clear(); continue; } count = 0; while (fin.get(ch)) count++; cout << count << " characters in " << argv[file] << endl; total += count; fin.clear(); fin.close(); } cout << total << " characters in all fileds:\n"; return 0;}

那两文件我自己创建的,然后里面随便输入一些字符

文件模式

在oepn函数中添加参数

使用位或运算符'|'来混合使用 比如打开追加 打开截断

代表性的组合

追加

#include 
#include
#include
#include
const char* file = "guests.txt";int main(){ using namespace std; char ch;// 读文件 ifstream fin; fin.open(file); if (fin.is_open()) { cout << "Here are the current contents of the " << file << " file:\n"; while(fin.get(ch)) cout << ch; fin.close(); }// 直接用构造函数关联文件 模式采用追加 取文件 ofstream fout(file, ios::out | ios::app); if (!fout.is_open()) { cerr << "Can't open " << file << " file for output.\n"; exit(EXIT_FAILURE); } cout << "Enter guest names (enter a blank line to quit):\n"; string name; while (getline(cin, name) && name.size() > 0) { fout << name << endl; } fout.close();// 读文件 fin.clear(); fin.open(file); if (fin.is_open()) { cout << "Here are the new contents of the " << file << " file:\n"; while (fin.get(ch)) cout << ch; fin.close(); } cout << "Done.\n"; return 0;}

运行结果 运行两次 第一次自动创建文件,第二次追加文件

二进制文件

二进制文件的读写统一用read()和writer()

程序示例

#include 
#include
#include
#include
// 用来将输入流中的换行符去掉inline void eatline() { while (std::cin.get() != '\n') continue;}struct planet{ char name[20]; double population; double g;};const char* file = "planets.dat";int main(){ using namespace std; planet p1; cout << fixed << right; ifstream fin; fin.open(file, ios_base::in | ios_base::binary); if (fin.is_open()) { cout << "Here are the current contents of the " << file << " file:\n";// 强转成char指针类型是因为read函数必须要该类型,并且保持类型一致 while(fin.read((char* ) &p1, sizeof p1)) { cout << setw(20) << p1.name << ": " << setprecision(0) << setw(12) << p1.population << setprecision(2) << setw(6) << p1.g << endl; } fin.close(); }// 追加写,二进制 ofstream fout(file, ios_base::out | ios_base::app | ios_base::binary); if (!fout.is_open()) { cerr << "Can't open " << file << " file for output:\n"; exit(EXIT_FAILURE); } cout << "Enter planet name (enter a blank line to quit):\n"; cin.get(p1.name, 20); while(p1.name[0] != '\0') { eatline(); cout << "Enter planetary population: "; cin >> p1.population; cout << "Enter planet's acceleration of gravity: "; cin >> p1.g; eatline(); fout.write((char* ) &p1, sizeof p1); cout << "Enter planet name (enter a blank line " << "to quit): \n"; cin.get(p1.name, 20); } fout.close(); fin.clear(); fin.open(file, ios_base::in | ios_base::binary); if(fin.is_open()) { cout << "Here are the new contents of the " << file << " file:\n"; while (fin.read((char*) &p1, sizeof p1)) { cout << setw(20) << p1.name << ": " << setprecision(0) << setw(12) << p1.population << setprecision(2) << setw(6) << p1.g << endl; } fin.close(); } cout << "Done.\n"; return 0;}

程序示例

结构体中不能用string类型 因为string返回的是指向字符串的地址。哪个保存到文件中是没有卵用的

随机存取

利用输入指针和输出指针在文件中随意跳转进行得写(其实是在缓冲区中)

seekg()输入指针

seekp()输出指针

原型

ios_base::seekdir是ios_base类中定义的另一种整形, 有3个值 ios_base::beg 文件开始的位置 ios_base::cur 当前位置的偏移量

ios_base::end文件尾

streamoff:相对于ios_base所指向的位置的特定距离(单位是字节)

streampos 指的是距离文件头的位置

 

他在说什么呢?

举例

输入流检查文件当前位置用tellg()

输出流检查用tellp()

返回的是streampos类型的值

#include 
#include
#include
#include
const int LIM = 20;struct planet{ char name[LIM]; double population; double g;};const char* file = "planets.dat";inline void eatline() {while (std::cin.get() != '\n') continue;}int main(){ using namespace std; planet pl; cout << fixed; fstream finout;// 读写字节格式 finout.open(file, ios_base::in | ios_base::out | ios_base::binary); int ct = 0; if (finout.is_open()) {// 输出流(读取)重置到文件开头 finout.seekg(0); cout << "Here are the current contents of the " << file << " file:\n"; while (finout.read((char*) &pl, sizeof pl)) { cout << ct++ << ": " << setw(LIM) << pl.name << ": " << setprecision(0) << setw(12) << pl.population << setprecision(2) << setw(12) << pl.g << endl; }// 文件结尾就清输出流缓存 if (finout.eof()) finout.clear(); else{ cerr << "Error in reading " << file << ".\n"; exit(EXIT_FAILURE); } } else { cerr << file << " could not be opened -- bye.\n"; exit(EXIT_FAILURE); } cout << "Enter the record number you wish to change: "; long rec; cin >> rec;//自定义函数 eatline(); if (rec < 0 || rec >= ct) { cerr << "Invalid record number -- bye\n"; exit(EXIT_FAILURE); }// stream类中自定义的int类型// 跳转到文件内容的相应位置,以一个planet为长度 streampos place = rec * sizeof pl; finout.seekg(place);// 出现超尾,报异常 if (finout.fail()) { cerr << "Error on attempted seek\n"; exit(EXIT_FAILURE); } finout.read((char*) &pl, sizeof pl); cout << "Your selection:\n"; cout << rec << ": " << setw(LIM) <
<< ": " << setprecision(0) << setw(12) << pl.population << setprecision(2) << setw(6) << pl.g << endl; if(finout.eof()) finout.clear(); cout << "Enter planet name: "; cin.get(pl.name, LIM); eatline(); cout << "Enter planetary population: "; cin >> pl.population; cout << "Enter planet's acceleration of gravity: "; cin >> pl.g;//输入流指针定位至客户要求的指定步长 finout.seekp(place); // flush表示手动刷新,一刷新数据就写入到文件中 finout.write((char *) &pl, sizeof pl) << flush; if(finout.fail()) { cerr << "Error on attempted write\n"; exit(EXIT_FAILURE); } ct = 0;// 重新定位输出流至文件流开头 finout.seekg(0); cout << "Here are the new contents of the " << file << " file:\n"; while(finout.read((char *) &pl, sizeof pl)) { cout << ct++ << ": " << setw(LIM) << pl.name << ": " << setprecision(0) << setw(12) << pl.population << setprecision(2) << setw(6) << pl.g << endl; } finout.close(); cout << "Done.\n"; return 0;}

运行结果

使用临时文件

嗯。。想得很周全,但是没啥软用 先留着吧

文件I/O完结

转载地址:http://vsepi.baihongyu.com/

你可能感兴趣的文章
Python爬虫进阶之JS逆向混淆加密和AES加密的破解
查看>>
Python爬虫进阶之JS逆向某视频网站登录
查看>>
火车票被秒光,别慌!快用Python来抢票!
查看>>
Python爬虫进阶之巧破RSA加密
查看>>
详解Flask 中的session 和 cookie的应用
查看>>
Python爬虫进阶之JS逆向混淆加密和AES加密的破解
查看>>
用Python来可视化微信好友
查看>>
用Python自动生成NBA历史巨星和现役球员生涯曲线
查看>>
Python爬虫进阶之某支付网站密码分析
查看>>
Python 系列教程 | 字符串
查看>>
Python爬虫偷懒神器 ---- 快速构造请求头!
查看>>
全面拥抱 FastApi — 多应用程序管理蓝图APIRouter
查看>>
全面拥抱FasiApi ——三大参数及验证
查看>>
Python爬虫|JS逆向调试技巧大全
查看>>
scrapy 出现 [twisted.internet.error.TimeoutError:] 的几种解决方案
查看>>
用Python分析了近几年富豪排行榜,我酸了...
查看>>
爬虫|如何在scrapy请求异常之后再设置代理IP
查看>>
当Django遇上Pyecharts将碰撞出怎样的火花……
查看>>
全面拥抱FastApi-优雅的处理HTTPException
查看>>
茅台抢购脚本详细教程!!!另已将茅台抢购做成了一个软件!!!
查看>>