本文共 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/