C中採用的主要是文件指針的辦法,C++中對文件的操做主要運用了「文件流」(即非標準的輸入輸出)的思想html
FILE *fopen(const char *filename, const char *mode)
使用給定的模式 mode 打開 filename 所指向的文件。ios
#include<stdio.h>
FILE *fopen(const char *filename, const char *mode)
filename -- 這是 C 字符串,包含了要打開的文件名稱。
mode -- 這是 C 字符串,包含了文件訪問模式,模式以下:c++
r 以只讀方式打開文件,該文件必須存在。
r+ 以可讀寫方式打開文件,該文件必須存在。
rb+ 讀寫打開一個二進制文件,容許讀數據。
rt+ 讀寫打開一個文本文件,容許讀和寫。
w 打開只寫文件,若文件存在則文件長度清爲0,即該文件內容會消失。若文件不存在則創建該文件。
w+ 打開可讀寫文件,若文件存在則文件長度清爲零,即該文件內容會消失。若文件不存在則創建該文件。
a 以附加的方式打開只寫文件。若文件不存在,則會創建該文件,若是文件存在,寫入的數據會被加到文件尾,即文件原先的內容會被保留。(EOF符保留)
a+ 以附加方式打開可讀寫的文件。若文件不存在,則會創建該文件,若是文件存在,寫入的數據會被加到文件尾後,即文件原先的內容會被保留。 (原來的EOF符不保留)
wb 只寫打開或新建一個二進制文件;只容許寫數據。
wb+ 讀寫打開或創建一個二進制文件,容許讀和寫。
wt+ 讀寫打開或着創建一個文本文件;容許讀寫。
at+ 讀寫打開一個文本文件,容許讀或在文本末追加數據,a表示append,就是說寫入處理的時候是接着原來文件已有內容寫入,不是從頭寫入覆蓋掉,t表示打開文件的類型是文本文件,+號表示對文件既能夠讀也能夠寫。
ab+ 讀寫打開一個二進制文件,容許讀或在文件末追加數據。windows
上述的形態字符串均可以再加一個b字符,如rb、w+b或ab+等組合,加入b 字符用來告訴函數庫以二進制模式打開文件。若是不加b,表示默認加了t,即rt,wt,其中t表示以文本模式打開文件。由fopen()所創建的新文件會具備S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)權限,此文件權限也會參考umask 值。數組
有些C編譯系統可能不徹底提供全部這些功能,有的C版本不用"r+","w+","a+",而用"rw","wr","ar"等,讀者注意所用系統的規定。緩存
文件使用方式由r,w,a,t,b,+六個字符拼成,各字符的含義是:app
r(read): 讀 w(write): 寫 a(append): 追加 t(text): 文本文件,可省略不寫 b(banary): 二進制文件 +: 讀和寫
1.在windows系統中,文本模式下,文件以"\r\n"表明換行。若以文本模式打開文件,並用fputs等函數寫入換行符"\n"時,函數會自動在"\n"前面加上"\r"。即實際寫入文件的是"\r\n" 。函數
2.在類Unix/Linux系統中文本模式下,文件以"\n"表明換行。因此Linux系統中在文本模式和二進制模式下並沒有區別。
返回值 : 若是文件順利打開,返回指向該流的文件指針。若是文件打開失敗則返回NULL,並把錯誤代碼存在error中。spa
通常而言,打開文件後會做一些文件讀取或寫入的動做,若打開文件失敗,接下來的讀寫動做也沒法順利進行,因此通常在fopen()後做錯誤判斷及處理。操作系統
1.做用: 在C語言中fopen()函數用於打開指定路徑的文件,獲取指向該文件的指針。
2.函數原型:
FILE * fopen(const char * path,const char * mode); -- path: 文件路徑,如:"F:\Visual Stdio 2012\test.txt" -- mode: 文件打開方式,例如: "r" 以只讀方式打開文件,該文件必須存在。 "w" 打開只寫文件,若文件存在則文件長度清爲0,即該文件內容會消失。若文件不存在則創建該文件。 "w+" 打開可讀寫文件,若文件存在則文件長度清爲零,即該文件內容會消失。若文件不存在則創建該文件。 "a" 以附加的方式打開只寫文件。若文件不存在,則會創建該文件,若是文件存在,寫入的數據會被加到文件尾,即文件原先的內容會被保留。(EOF符保留) "a+" 以附加方式打開可讀寫的文件。若文件不存在,則會創建該文件,若是文件存在,寫入的數據會被加到文件尾後,即文件原先的內容會被保留。(原來的EOF符不保留) "wb" 只寫打開或新建一個二進制文件,只容許寫數據。 "wb+" 讀寫打開或創建一個二進制文件,容許讀和寫。 "ab" 追加打開一個二進制文件,並在文件末尾寫數據。 "ab+"讀寫打開一個二進制文件,容許讀,或在文件末追加數據。 --返回值: 文件順利打開後,指向該流的文件指針就會被返回。若是文件打開失敗則返回NULL,並把錯誤代碼存在errno中。
1.做用:在C語言中fwrite()函數經常使用語將一塊內存區域中的數據寫入到本地文本。
2.函數原型:
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream); -- buffer:指向數據塊的指針 -- size:每一個數據的大小,單位爲Byte(例如:sizeof(int)就是4) -- count:數據個數 -- stream:文件指針
注意:
返回值隨着調用格式的不一樣而不一樣:
(1) 調用格式:fwrite(buf,sizeof(buf),1,fp);
成功寫入返回值爲1(即count)
(2)調用格式:fwrite(buf,1,sizeof(buf),fp);
成功寫入則返回實際寫入的數據個數(單位爲Byte)
寫完數據後要調用fclose()關閉流,不關閉流的狀況下,每次讀或寫數據後,文件指針都會指向下一個待寫或者讀數據位置的指針。
代碼1: 下面代碼可將1024個字(int)寫入到文本文件,fwrite的調用中,size是sizeof(int),count是DATA_SIZE
#include "stdafx.h" #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #define DATA_SIZE 1024 int main() { unsigned int *dataPtr = NULL; dataPtr = (unsigned int *)malloc(sizeof(int)*DATA_SIZE); for(unsigned int i=0;i<DATA_SIZE;i++) { dataPtr[i] = i; //初始化緩存區 } FILE *fp = fopen("F:\\Labwindows cvi\\test.txt","w"); fwrite(dataPtr,sizeof(int),DATA_SIZE,fp); fclose(fp); free(dataPtr); system("pause"); return 0; }
代碼2:
下面代碼也可將1024個字寫到文本中,雖然fwrite函數中,size是1,但count是DATA_SIZE*sizeof(int)。與代碼1實現的結果同樣。
// datasave.cpp : 定義控制檯應用程序的入口點。 // #include "stdafx.h" #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #define DATA_SIZE 1024 int main() { unsigned int *dataPtr = NULL; dataPtr = (unsigned int *)malloc(sizeof(int)*DATA_SIZE); for(unsigned int i=0;i<DATA_SIZE;i++) { dataPtr[i] = i; //初始化緩存區 } FILE *fp = fopen("F:\\Labwindows cvi\\test.txt","ab+"); fwrite(dataPtr,1,DATA_SIZE*sizeof(unsigned int),fp); fclose(fp); free(dataPtr); system("pause"); return 0; }
下面的代碼將4096個char數據寫到文本,寫入的數據中,最大值爲255,與上面代碼一、2有區別,由於緩存區數據類型不一樣
// datasave.cpp : 定義控制檯應用程序的入口點。 // #include "stdafx.h" #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #define DATA_SIZE 1024 int main() { unsigned char *dataPtr = NULL; dataPtr = (unsigned char *)malloc(sizeof(int)*DATA_SIZE); //申請的區域是4096個char,即1024個字的區域 for(unsigned int i=0;i<DATA_SIZE;i++) { dataPtr[i] = i; //初始化緩存區 } FILE *fp = fopen("F:\\Labwindows cvi\\test.txt","ab+"); fwrite(dataPtr,sizeof(char),DATA_SIZE*sizeof(int),fp); fclose(fp); free(dataPtr); system("pause"); return 0; }
用malloc函數申請區域時是申請的一片char*區域,經過強制類型轉換後可裝unsigned int 數據。
// datasave.cpp : 定義控制檯應用程序的入口點。 // #include "stdafx.h" #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #define DATA_SIZE 1024 int main() { unsigned char *dataPtr = NULL; unsigned int *Ptr = NULL; dataPtr = (unsigned char *)malloc(sizeof(int)*DATA_SIZE); Ptr = (unsigned int *) dataPtr; for(unsigned int i=0;i<DATA_SIZE;i++) { Ptr[i] = i; } FILE *fp = fopen("F:\\Labwindows cvi\\test.txt","ab+"); fwrite(Ptr,sizeof(unsigned int),DATA_SIZE,fp); fclose(fp); free(dataPtr); system("pause"); return 0; }
size_t fread(void *buffer, size_t size, size_t count, FILE *stream); -- buffer:指向數據塊的指針 -- size:每一個數據的大小,單位爲Byte(例如:sizeof(int)就是4) -- count:數據個數 -- stream:文件指針
注意:返回值隨着調用格式的不一樣而不一樣:
(1) 調用格式:fread(buf,sizeof(buf),1,fp);
讀取成功時:當讀取的數據量正好是sizeof(buf)個Byte時,返回值爲1(即count)
不然返回值爲0(讀取數據量小於sizeof(buf))
(2)調用格式:fread(buf,1,sizeof(buf),fp);
讀取成功返回值爲實際讀回的數據個數(單位爲Byte)
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { FILE *filp = NULL; char fileDir[] = "/home/yangzhiyuan/Documents/test.txt"; char dataPtr[] = "Helloworld"; printf("sizeof(dataPtr) = %ld\n",sizeof(dataPtr)); filp = fopen(fileDir,"w+"); /* 可讀可寫,不存在則建立 */ int writeCnt = fwrite(dataPtr,sizeof(dataPtr),1,filp); /* 返回值爲1 */ //int writeCnt = fwrite(dataPtr,1,sizeof(dataPtr),filp); /* 返回值爲11 */ printf("writeCnt = %d\n",writeCnt); fclose(filp); FILE *fp = NULL; fp = fopen(fileDir,"r"); char buffer[256]; int readCnt = fread(buffer,sizeof(buffer),1,fp); /* 返回值爲0 */ //int readCnt = fread(buffer,1,sizeof(buffer),fp); /* 返回值爲11 */ printf("readCnt = %d\n",readCnt); fclose(fp); printf("%s\n",buffer); exit(0); }
本例代碼中定義了兩個FILE變量,一個用於write,一個用於read,寫完後要close掉,而後再打開,而後讀。若是直接使用一個FILE變量,會出錯!
// 讀取文件塊數據 size_t fread(void *buffer, size_t size, size_t count, FILE *file); // 寫入文件塊數據 size_t fwrite(const void *buffer, size_t size, size_t count, FILE *file);
fread參數說明:buffer是讀取數據後存放地址,size是的塊長度,count是塊的數量,實際讀取長度爲size*count,返回值爲塊成功讀取塊的count數量。
fwrite參數說明:buffer是寫入數據後存放地址,size是的塊長度,count是塊的數量,實際讀取長度爲size*count,返回值爲塊成功寫入快的count數量。
寫文件
#include <stdio.h> #include <stdlib.h> int main() { FILE * fp; fp = fopen ("file.txt", "w+"); fprintf(fp, "%s %s %s %d", "We", "are", "in", 2014); fclose(fp); return(0); }
輸出
We are in 2014
查看上面的內容:
#include <stdio.h> int main () { FILE *fp; int c; fp = fopen("file.txt","r"); while(1) { c = fgetc(fp); if( feof(fp) ) { break ; } printf("%c", c); } fclose(fp); return(0); }
#include <fstream>
fstream提供三種類,實現C++對文件的操做
ofstream:寫操做,由ostream引伸而來
ifstream:讀操做,由istream引伸而來
fstream :同時讀寫操做,由iostream引伸而來
文本文件 和 二進制文件
ios::in 爲輸入(讀)而打開文件;
ios::out 爲輸出(寫)而打開文件;
ios::ate 初始位置:文件尾;
ios::app 全部輸出附加在文件末尾;
ios::trunc 若是文件已存在則先刪除該文件;
ios::binary 二進制方式;
ios::nocreate:不創建文件,因此文件不存在時打開失敗;
ios::noreplace:不覆蓋文件,因此打開文件時若是文件存在失敗;
這些標識符能夠被組合使用,中間以」或」操做符(|)間隔。例如,若是咱們想要以二進制方式打開文件"example.bin" 來寫入一些數據,咱們能夠經過如下方式調用成員函數open()來實現:
ofstream file; file.open ("example.bin", ios::out | ios::app | ios::binary);
ofstream, ifstream 和 fstream全部這些類的成員函數open 都包含了一個默認打開文件的方式,這三個類的默認方式各不相同:
ofstream 默認方式 ios::out | ios::trunc
ifstream 默認方式 ios::in
fstream 默認方式 ios::in | ios::out
只有當函數被調用時沒有聲明方式參數的狀況下,默認值纔會被採用。若是函數被調用時聲明瞭任何參數,默認值將被徹底改寫,而不會與調用參數組合。
因爲對類ofstream, ifstream 和 fstream 的對象所進行的第一個操做一般都是打開文件,這些類都有一個構造函數能夠直接調用open 函數,並擁有一樣的參數。這樣,咱們就能夠經過如下方式進行與上面一樣的定義對象和打開文件的操做:
ofstream file ("example.bin", ios::out | ios::app | ios::binary);
兩種打開文件的方式都是正確的。
你能夠經過調用成員函數is_open()來檢查一個文件是否已經被順利的打開了:
bool is_open();
它返回一個布爾(bool)值,爲真(true)表明文件已經被順利打開,假( false )則相反。
關閉文件(Closing a file)
當文件讀寫操做完成以後,咱們必須將文件關閉以使文件從新變爲可訪問的。關閉文件須要調用成員函數close(),它負責將緩存中的數據排放出來並關閉文件。它的格式很簡單:
void close ();
這個函數一旦被調用,原先的流對象(stream object)就能夠被用來打開其它的文件了,這個文件也就能夠從新被其它的進程(process)全部訪問了。
爲防止流對象被銷燬時還聯繫着打開的文件,析構函數(destructor)將會自動調用關閉函數close。
除了eof()之外,還有一些驗證流的狀態的成員函數(全部都返回bool型返回值):
bad()
若是在讀寫過程當中出錯,返回 true 。例如:當咱們要對一個不是打開爲寫狀態的文件進行寫入時,或者咱們要寫入的設備沒有剩餘空間的時候。
fail()
除了與bad() 一樣的狀況下會返回 true 之外,加上格式錯誤時也返回true ,例如當想要讀入一個整數,而得到了一個字母的時候。
eof()
若是讀文件到達文件末尾,返回true。
good()
這是最通用的:若是調用以上任何一個函數返回true 的話,此函數返回 false 。
要想重置以上成員函數所檢查的狀態標誌,你可使用成員函數clear(),沒有參數。
一、包含的頭文件:#include
二、建立流
三、打開文件(文件和流關聯)
四、讀寫 (寫操做:<<,put( ), write( ) 讀操做: >> , get( ),getline( ), read( ))
五、關閉文件:把緩衝區數據完整地寫入文件, 添加文件結束標誌, 切斷流對象和外部文件的鏈接
一、文本文件的讀寫:
方法:
一次性讀寫若干字符
1)使用運算符<< 和 >>進行讀寫 功能: << 能實現以行爲單位寫入文件 >> 不能一行爲單位讀入內存,老是以空格、Tab、回車結束,而是以單詞爲單位
代碼:
函數功能:使用<< ,寫入文件一行字符
#include <fstream> #include <iostream> using namespace std; void main() { ofstream OpenFile("file.txt"); if (OpenFile.fail()) { cout<<"打開文件錯誤!"<<endl; exit(0); } OpenFile<<"abc def ghi"; OpenFile.close(); system("pause"); }
運行結果:文件中寫入內容:abc def ghi
函數功能:使用>>,從文件讀入一個單詞
#include <fstream> #include <iostream> using namespace std; void main() { const int len=20; char str[len]; ifstream OpenFile("file.txt"); if (OpenFile.fail()) { cout<<"打開文件錯誤!"<<endl; exit(0); } OpenFile>>str; cout<<str<<endl; OpenFile.close(); system("pause"); }
運行結果:str的內容爲abc,而不是abc def ghi(見空格中止)
功能: <<:以行爲單位輸入文件 getline():以行爲單位 讀入內存,能一次讀入一行 函數原型:istream &getline( char *buffer, streamsize num ); 功能:getline( )函數用於從文件讀取num-1個字符到buffer(內存)中,直到下列狀況發生時,讀取結束: 1):num - 1個字符已經讀入 2):碰到一個換行標誌 3):碰到一個EOF
代碼:
#include <fstream> #include <iostream> using namespace std; void main() { const int len=20; char str[len]; ifstream OpenFile("file.txt"); if (OpenFile.fail()) { cout<<"打開文件錯誤!"<<endl; exit(0); } OpenFile.getline(str,20); cout<<str<<endl; OpenFile.close(); system("pause"); }
運行結果:str的內容爲abc def ghi (一直把一行讀完)
使用get( )和put( )函數
函數聲明:istream& get(char &c);
函數功能:使用 get( )函數 把字符1輸入到文件
#include <fstream> #include <iostream> using namespace std; void main() { char ch='1'; ofstream OpenFile("file.txt"); if (OpenFile.fail()) { cout<<"打開文件錯誤!"<<endl; exit(0); } OpenFile.put(ch); OpenFile.close(); system("pause"); }
運行結果:把字符1寫入文件
函數功能:使用 put( )函數 把文件中第一個字符輸入內存
#include <fstream> #include <iostream> using namespace std; void main() { char ch; ifstream OpenFile("file.txt"); if (OpenFile.fail()) { cout<<"打開文件錯誤!"<<endl; exit(0); } OpenFile.get(ch); cout<<ch; OpenFile.close(); system("pause"); }
運行結果:把字符1從文件中讀到ch(內存)中
1)使用運算符get( ) 和 put( )讀寫一個字節
功能:
get( ) :在文件中讀取一個字節到內存
函數原型:ifstream &get(char ch)
put( ) :在內存中寫入一個字節到文件
函數原型:ofstream &put(char ch)
代碼:
功能:把26個字符寫入文件中
#include <fstream> #include <iostream> using namespace std; void main() { char ch='a'; ofstream OpenFile("file.txt",ios::binary); if (OpenFile.fail()) { cout<<"打開文件錯誤!"<<endl; exit(0); } for (int i=0;i<26;i++) { OpenFile.put(ch); ch++; } OpenFile.close(); system("pause"); }
運行結果:文件內容爲abcdefghijklmnopqlst...z
功能:把文件中的26個字母讀入內存
#include <fstream> #include <iostream> using namespace std; void main() { char ch; ifstream OpenFile("file.txt",ios::binary); if (OpenFile.fail()) { cout<<"打開文件錯誤!"<<endl; exit(0); } while (OpenFile.get(ch)) cout<<ch; OpenFile.close(); system("pause"); }
運行結果:ch依次爲abc...z
read( ):
功能:從文件中提取 n 個字節數據,寫入buf指向的地方中 函數聲明:istream & read ( char * buf , int n ) ;
代碼:
函數功能:使用write( )函數,一次從內存向文件寫入一行數據
#include <fstream> #include <iostream> using namespace std; void main() { char ch[12]="12 3 456 78"; ofstream OpenFile("file.txt"); if (OpenFile.fail()) { cout<<"打開文件錯誤!"<<endl; exit(0); } OpenFile.write(ch,12); OpenFile.close(); system("pause"); }
運行結果:文件內容12 3 456 78
write( ):
功能:把buf指向的內容取n個字節寫入文件 函數聲明:ostream & ostream :: write ( char * buf , int n ) ; 參數說明:buf表示要寫入內存的地址,傳參時要取地址。n表示要讀入字節的長度 注意:1):該函數遇到空字符時並不中止,於是可以寫入完整的類結構 2):第一個參數一個char型指針(指向內存數據的起始地址),與對象結合使用的時候,要在對象地址以前要char作強制類型轉換。
函數功能:使用write( )函數,一次從文件向內存寫入一行數據
#include <fstream> #include <iostream> using namespace std; void main() { char ch[12]; ifstream OpenFile("file.txt"); if (OpenFile.fail()) { cout<<"打開文件錯誤!"<<endl; exit(0); } OpenFile.read(ch,12); cout<<ch; OpenFile.close(); system("pause"); }
運行結果:數組ch的內容爲12 3 456 78 。
一、程序再也不使用文件時,爲何要關閉文件?
由於:
1)文件緩衝區是一塊小的內存空間.
2)操做系統限制同時打開的文件數量
注意:close ( ) 函數關閉文件,但流對象仍然存在。
二、文件的默認打開方式爲文本文件,要是想以二進制的方式處理,在打開時要用 ios::binary 顯式聲明。
三、針對文本文件操做時,get函數和>>的區別:
區別:在讀取數據時,get函數包括空白字符(遇空白字符不中止讀取)
>>在默認狀況下拒絕接受空白字符(遇到空白符中止讀取)
四、判斷文件是否打開的方法:
if (OpenFile) { cout<<"打開文件失敗!"; exit(0); } if (OpenFile.fail()) { cout<<"打開文件錯誤!"<<endl; exit(0); }
1)使用成員函數eof()能夠檢測到這個結束符,若是非0表示文件結束。
while (!OpenFile.eof()) { //文件結束時的代碼 }
2)使用流直接檢測,若是爲0表示文件結束
while (!OpenFile) { //文件結束時的代碼 }
3)使用get函數,讀取最後一個結束符時,返回0.讀取正常狀況下,返回1,並把讀取的字符放到ch中
while ( (OpenFile.get(ch) )!=EOF) { //成功時候的代碼 }
文本文件的讀寫常使用的方法:使用<<寫入文件,使用getline 和 >> 讀到內存
二進制文件的讀寫常使用的方法:使用istream 類的成員函數read 和write 來實現,
這兩個成員函數的原型爲:
istream& read(char *buffer,int len); ostream& write(const char * buffer,int len);
參數說明:字符指針 buffer 指向內存中一段存儲空間。len 是讀/寫的字節數。
與對象結合寫入二進制文件時:
輸出文件流對象名.write((char*)& 對象名,sizeof(<對象所屬類名>)); 輸出文件流對象名.write((char*)& 對象數組名[下標],sizeof(<對象所屬類名>));
輸入文件流對象名.read((char*)& 對象名,sizeof(<對象所屬類名>)); 輸入文件流對象名.read((char*)& 對象數組名[下標],sizeof(<對象所屬類名>));
注意:gcount()函數常常和read函數配合使用,用來得到實際讀取的字節數。
#include <iostream> #include <fstream> using namespace std; int main(void) { //寫文件:二進制存儲1234 int writeNum1 = 1; int writeNum2 = 2; int writeNum3 = 3; int writeNum4 = 4; ofstream fout("test.txt", ios::out | ios::binary); fout.write(reinterpret_cast<char *>(&writeNum1), sizeof(int)); fout.write(reinterpret_cast<char *>(&writeNum2), sizeof(int)); fout.write(reinterpret_cast<char *>(&writeNum3), sizeof(int)); fout.write(reinterpret_cast<char *>(&writeNum4), sizeof(int)); fout.close(); //讀文件 ifstream fin("test.txt",ios::in | ios::binary); if (!fin.good()) { cout<<"文件打開錯誤"<<endl; exit(0); } int readNum = 0; //第一次輸出:從第一個數字輸出,結果是1 2 3 4 fin.seekg(0,ios::beg); while (fin.peek() != EOF) { fin.read(reinterpret_cast<char*>(&readNum), sizeof(int)); cout<<readNum<<" "; } cout<<endl; //第二次輸出:從第三個數字輸出,結果是3 4 fin.seekg(2 * sizeof(int),ios::beg);//遊標移動的次數 = 須要處理數的個數 × int佔的字節數 while (fin.peek() != EOF) { fin.read(reinterpret_cast<char*>(&readNum), sizeof(int)); cout<<readNum<<" "; } cout<<endl; fin.close(); system("pause"); return 0; }