1. 文件操作
通過文件將數據持久化
C++ 對文件操作需要包含頭文件<fstream>
文件類型分為兩種:
操作文件的三大類:
ofstream --- 寫操作
ifstream --- 讀操作
fstream --- 讀寫操作
2. 文本文件
1)寫文件步驟
1. 包含頭文件#include <fstream>2. 創建流對象ofstream ofs;3. 打開文件ofs.open("文件路徑", 打開方式);4. 寫數據ofs << "寫入數據";5. 關閉文件ofs.close();文件打開方式:
打開方式 解釋ios::in 為讀文件而打開文件ios::out 為寫文件而打開文件ios::ate 初始位置:文件尾ios::app 追加方式寫文件ios::trunc 如果文件存在先刪除,再創建ios::binary 二進位方式註:文件打開方式可以配合使用,利用 | 操作符
例如用二進位方式寫文件 ios::binary | ios::out
2)讀文件步驟
1. 包含頭文件#include<fstream>2. 創建流對象ifstream ifs;3. 打開文件並判斷文件是否打開成功ifs.open("文件路徑",打開方式);4. 讀數據四種方式讀取5. 關閉文件ifs.close();判斷是否打開成功 ifs.is_open()
void test(){ ifstream ifs; ifs.open("text.txt",ios::in); if(!ifs.is_open()) { cout << "文件打開失敗" << endl; return; } char buf[1024] = { 0 }; while (ifs >> buf) { cout << buf << endl; }
char buf[1024] = { 0 }; while (ifs.getline(buf, sizeof(buf))) { cout << buf << endl; }
string buf; while (getline(ifs, buf)) { cout << buf << endl; }
char c; while ((c = ifs.get()) != EOF) { cout << c; }}3. 二進位文件
以二進位方式對文件進行讀寫操作
打開方式要指定為 ios::binary
寫文件:
利用流對象調用成員函數 write
ostream& write(const char *buffer,int len);class Person {public: char m_Name[64]; int m_Age;};
void test(){ ofstream ofs; ofs.open("person.txt", ios::out | ios::binary); Person p = { "張三",20 }; ofs.write((const char*)&p, sizeof(Person)); ofs.close();}讀文件:
利用流對象調用成員函數read
istream& read(char *buffer, int len);// 字符指針buffer指向內存中一段存儲空間。len是讀寫的字節數class Person {public: char m_Name[64]; int m_Age;};
void test(){ ifstream ifs("person.txt", ios::in | ios::binary); if (!ifs.is_open()) { cout << "文件不存在" << endl; return; } Person p; ifs.read((char*)&p, sizeof(Person)); cout << "name = " << p.m_Name << " ,age = " << p.m_Age << endl; ifs.close();}3. 流處理
C++引入 istringstream(串流的輸入)、ostringstream(串流的輸出)、stringstream(串流的輸入輸出),使用時要包含sstream.h的頭文件。
當 cin 讀取數據時,它會傳遞並忽略任何前導白色空格字符(空格、制表符或換行符)。一旦它接觸到第一個非空格字符即開始閱讀,當它讀取到下一個空白字符時,它將停止讀取。
int main(){ string name; string city; cout << "Please enter your name: "; cin >> name; cout << "Enter the city you live in: "; cin >> city; cout << "Hello, " << name << endl; cout << "You live in " << city << endl; return 0;}輸入:Jone Merry輸出:Hello, Jone You live in Merrygetline 此函數可讀取整行,包括前導和嵌入的空格,並將其存儲在字符串對象中。
getline(istream &is,string &str,char delim)從stringstream流中的數據輸入字符串到一個變量裡,是以遇到空格跳到下一個字符串的這樣的形式連續讀取的。
輸入形式:a c bbf ddddnowcoder
using namespace std;int main(){ string str; while(getline(cin, str))// getline 按行讀取 { vector<string>s; string tmp; stringstream ss(str); while(ss>>tmp){ s.push_back(tmp); } sort(s.begin(),s.end()); for(int i=0;i<s.size()-1;i++){ cout<<s[i]<<" "; } cout<<s[s.size()-1]<<endl; str.clear(); }}輸入形式:a,c,bbf,ddddnowcoder
#include<bits/stdc++.h>using namespace std;int main(){ string str; while(getline(cin, str)){ stringstream ss(str); vector<string>s; string tmp; while(getline(ss, tmp, ',')){ s.push_back(tmp); } sort(s.begin(),s.end()); for(int i=0;i<s.size()-1;i++){ cout<<s[i]<<','; } cout<<s[s.size()-1]<<endl; }}C語言文件操作
1. 文件類型:
文本文件和二進位文件
數據在內存中是怎麼存儲的?
字符一律以ASCII形式存儲,數值型數據既可以用ASCII形式存儲,也可以使用二進位形式存儲
文件緩衝區:
標準C採用「緩衝文件系統」處理數據文件。緩衝文件系統 是指系統自動地在內存中為程序中每一個正在使用的文件開闢一塊「文件緩衝區」。緩衝區的大小根據C編譯系統決定。
文件指針:
緩衝文件系統中,關鍵的概念是「文件類型指針」,簡稱 文件指針。
每個被使用的文件都在內存中開闢了一個相應的文件信息區,用來存放文件的相關信息(如文件名,文件狀態,文件的當前位置等)。這些信息是保存在一個結構體變量中的。該結構體類型是由系統聲明的,取名 FILE
每當打開一個文件時,系統會根據文件的情況自動創建一個FILE結構的變量,並填充其中的信息,使用者不必關心細節。
定義pf是一個指向FILE類型數據的指針變量。可以使pf指向某個文件的文件信息區(是一個結構體變量)。通過該文件信息區中的信息就能夠訪問該文件。即,通過文件指針變量能夠找到與它關聯的文件
2. 文件讀寫操作
在編寫程序時,打開文件的同時,都會返回一個FILE*的指針變量指向該文件,也相當於建立了指針和文件的關係。
標準C(ANSIC)規定使用fopen打開文件,fclose關閉文件
FILE *fopen(const char *fileName, const char *mode);int fclose(FILE *stream);打開方式:
文件使用方式 含義 若指定文件不存在"r"(只讀) 為了輸入數據打開已存在的文本文件 出錯"w"(只寫) 為了輸出數據打開一個文本文件 新建"a"(追加) 向文本文件尾添加數據 出錯"rb"(只讀) 為了輸入數據打開一個二進位文件 出錯"wb"(只寫) 為了輸出數據打開一個二進位文件 新建"ab"(讀寫) 向一個二進位文件尾添加數據 出錯"r+"(讀寫) 為了讀和寫 打開一個文本文件 出錯"w+"(讀寫) 為了讀和寫 建立一個新的文件 新建"a+"(讀寫) 打開一個文件 在文件尾進行讀寫 新建"rb+"(讀寫) 為了讀和寫 打開一個二進位文件 出錯"wb+"(讀寫) 為了讀和寫 新建一個二進位文件 新建"ab+"(讀寫) 打開一個二進位文件 在文件尾進行讀和寫 新建#define _CRT_SECURE_NO_WARNINGS 1#include <errno.h>#include <string.h>
int main(){ FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { printf("%s\n", strerror(errno)); return 0; } fclose(pf); pf = NULL; return 0;}文件的順序讀寫:
功能 函數名 適用於字符輸入函數 fgetc 所有輸入流字符輸出函數 fputc 所有輸出流文本行輸入函數 fgets 所有輸入流文本行輸出函數 fputs 所有輸出流格式化輸入函數 fscanf 所有輸入流格式化輸出函數 fprintf 所有輸出流二進位輸入 fread 文件二進位輸出 fwrite 文件int main(){ FILE* pfWrite = fopen("test.txt", "w"); if (pfWrite == NULL) { printf("%s\n", strerror(errno)); return 0; } fputc('b', pfWrite); fputc('w', pfWrite); fclose(pfWrite); pfWrite = NULL; return 0;}鍵盤 屏幕 int main(){ int ch = fgetc(stdin);// 從標準輸入流輸入 fputc(ch,stdout);// 輸出到標準輸出流 return 0;}int main(){ FILE* pfRead = fopen("test.txt", "r"); if (pfRead == NULL) { printf("%s\n", strerror(errno)); return 0; } char buf[1024] = { 0 }; fgets(buf, 1024, pfRead); printf("%s", buf); fgets(buf, 1024, pfRead); printf("%s", buf); fclose(pfRead); pfRead = NULL; return 0; }struct S { int n; float score; char arr[10];};
int main(){ struct S s = { 100,3.14f,"hello" }; FILE* pf = fopen("test.txt", "w"); if (pf == NULL) { printf("%s\n", strerror(errno)); return 0; } fprintf(pf, "%d %f %s", s.n, s.score, s.arr); fclose(pf); pf = NULL; return 0;}struct S { int n; float score; char arr[10];};
int main(){ struct S s = { 100,3.14f,"hello" }; struct S tmp = { 0 }; char buf[1024] = { 0 }; sprintf(buf, "%d %f %s", s.n, s.score, s.arr); sscanf(buf, "%d %f %s", &(tmp.n), &(tmp.score), tmp.arr); printf("%d %f %s\n", tmp.n, tmp.score, tmp.arr); system("pause"); return 0;}scanf/printf 針對標準輸入流/輸出流的 格式化輸入/輸出語句fscanf/fprintf 針對所有輸入流/輸出流的 格式化輸入/輸出語句sscanf/sprintf 從字符串中讀取格式化的數據/把格式化數據輸出成字符串文件的隨機讀寫:
fseek:根據文件指針的位置和偏移量來定位文件指針
int fseek(FILE *stream, long int offset, int origin);ftell:返回文件指針相對於起始位置的偏移量
long int ftell(FILE *stream);int main(){ FILE* pf = fopen("test.txt", "r"); if (pf == NULL) return 0; fseek(pf, -2, SEEK_END); int pos = ftell(pf); printf("%d\n", pos); fclose(pf); pf = NULL; return 0;}rewind:讓文件指針的位置回到文件的起始位置
void rewind(FILE *stream)feof:
在文件讀取過程中,不能用feof函數的返回值直接判斷文件是否結束
而是 應用於當文件讀取結束時,判斷是讀取失敗結束,還是遇到文件尾結束
文本文件讀取是否結束,判斷返回值是否為EOF(用fgetc函數時判斷EOF),或者NULL(fgets)
二進位文件的讀取結束判斷,判斷返回值是否小於實際要讀取的個數
int main(){ int c; FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { perror("File open failed"); return 0; } while ((c = fgetc(pf)) != EOF) { putchar(c); } if (ferror(pf)) puts("I/O error when reading"); else if (feof(pf)) puts("End of file reached success");
fclose(pf); pf = NULL; system("pause"); return 0;}