以前學C語言的時候學習過標準IO和文件IO,現在再來複習整理下,並學習下c++的IO。
1.什麼是標準IO:
標準I/O是ANSI C建立的一個標準I/O模型,是一個標準函數包和stdio.h頭文件中的定義,具有一定的可移植性。標準IO庫處理很多細節。例如緩存分配,以優化長度執行IO等。標準的IO提供了三種類型的緩存。(1)全緩存:當填滿標準IO緩存後才進行實際的IO操作。 (2)行緩存:當輸入或輸出中遇到新行符時,標準IO庫執行IO操作。 (3)不帶緩存:stderr就是了。stdin:標準輸入 ,stdout:標準輸出 ,stderr:標準錯誤輸出。C++爲用戶進行標準I/O操作定義了四個類對象: cin,cout,cerr和clog。
2.是什麼文件IO:
文件IO稱之爲不帶緩存的IO(unbuffered I/O)。不帶緩存指的是每個read,write都調用內核中的一個系統調用。也就是一般所說的低級I/O——操作系統提供的基本IO服務,與os綁定,特定於linix或unix平臺。
3.兩者區別:
首先:兩者一個顯著的不同點在於,標準I/O默認採用了緩衝機制,比如調用fopen函數,不僅打開一個文件,而且建立了一個緩衝區(讀寫模式下將建立兩個緩衝區),還創建了一個包含文件和緩衝區相關數據的數據結構。低級I/O一般沒有采用緩衝,需要自己創建緩衝區,不過其實在linix或unix系統中,都是有使用稱爲內核緩衝的技術用於提高效率,讀寫調用是在內核緩衝區和進程緩衝區之間進行的數據複製。其次從操作的設備上來區分,文件I/O主要針對文件操作,讀寫硬盤等,它操作的是文件描述符,標準I/O針對的是控制檯,打印輸出到屏幕等,它操作的是字符流。對於不同設備得特性不一樣,必須有不同api訪問才最高效。
stdin示例(需要std=c++11):
#include <iostream>
using namespace std;
int main()
{
const int size = 10;
char buf[10] = "";
//c++標準輸入一行 , 回車鍵結束
cin.getline(buf,size);
cout<<"cin read : "<<buf<<endl;
//c使用標準輸入讀取鍵盤數據,\n結束
while(NULL != fgets(buf,size,stdin)){
printf("Read : %s",buf);
}
return 0;
}
stdout示例(需要std=c++11):
#include <iostream>
using namespace std;
int main()
{
char buf[] = "I'm stdout";
fprintf(stdout,"%s\n",buf);
return 0;
}
stderr示例(需要std=c++11):
#include <iostream>
using namespace std;
int main()
{
char buf[] = "I'm stderr";
fprintf(stderr,"%s\n",buf);
return 0;
}
OK,接下來是文件IO相關的內容與代碼咯。
前面我們已經使用了 iostream 標準庫,它提供了 cin 和 cout 方法分別用於從標準輸入讀取流和向標準輸出寫入流。文件讀取流和向文件寫入流。這就需要用到 C++ 中另一個標準庫 fstream,它定義了三個新的數據類型:
- ofstream:該數據類型表示輸出文件流,用於創建文件並向文件寫入信息。
- ifstream :該數據類型表示輸入文件流,用於從文件讀取信息。
- fstream :該數據類型通常表示文件流,且同時具有 ofstream 和 ifstream 兩種功能,這意味着它可以創建文件,向文件寫入信息,從文件讀取信息。
這些類直接的或者間接的繼承自istream和ostream。我們經常使用的istream和ostream的類是標準庫中的 cin 和cout。
打開文件:
在從文件讀取信息或者向文件寫入信息之前,必須先打開文件。ofstream 和 fstream 對象都可以用來打開文件進行寫操作,如果只需要打開文件進行讀操作,則使用 ifstream 對象。
//open() 函數的標準語法,open() 函數是 fstream、ifstream 和 ofstream 對象的一個成員。
void open(const char *filename, ios::openmode mode);
第二個參數爲操作模式如下:
模式標誌 描述
ios::app 追加模式。所有寫入都追加到文件末尾。
ios::ate 文件打開後定位到文件末尾。
ios::in 打開文件用於讀取。
ios::out 打開文件用於寫入。
ios::trunc 如果該文件已經存在,其內容將在打開文件之前被截斷,即把文件長度設爲 0。
你也可以進行多種模式組合 例如:
//寫入模式打開文件,並希望截斷文件,以防文件已存在
ofstream outfile;
outfile.open("file.dat", ios::out | ios::trunc );
//進行讀寫操作
ifstream afile;
afile.open("file.dat", ios::out | ios::in );
寫入文件:
使用的是 ofstream 或 fstream 對象,進行寫入。
讀取文件:
使用的是 ifstream 或 fstream 對象,進行讀取。
讀取與寫入文件示例(ifstream&ofstream):
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
char data[100];
// 以寫模式打開文件
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
cin.getline(data, 100);
// 向文件寫入用戶輸入的數據
outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();
// 再次向文件寫入用戶輸入的數據
outfile << data << endl;
// 關閉打開的文件
outfile.close();
// 以讀模式打開文件
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// 在屏幕上寫入數據
cout << data << endl;
// 再次從文件讀取數據,並顯示它
infile >> data;
cout << data << endl;
// 關閉打開的文件
infile.close();
return 0;
}
讀寫文件操作(fstream):
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char data[50];
fstream myfile;
//使用ios::app 定位於文件末端,所以讀寫都在之前文件的末端開始
myfile.open("myfile.dat", ios::app|ios::out|ios::in);
cin>>data;
cin.ignore();
//將數據寫入文件
myfile<<data;
//使用afile.seekg(ios::beg);,讓文件重新定位到開頭
//afile.seekg(ios::beg);
//將數據從文件中讀取出來
myfile>>data;
cout<<data<<endl;
myfile.close();
return 0;
}
文件位置指針:
istream 和 ostream 都提供了用於重新定位文件位置指針的成員函數。這些成員函數包括關於 istream 的 seekg("seek get")和關於 ostream 的 seekp("seek put")。
seekg 和 seekp 的參數通常是一個長整型。第二個參數可以用於指定查找方向。查找方向可以是 ios::beg(默認的,從流的開頭開始定位),也可以是 ios::cur(從流的當前位置開始定位),也可以是 ios::end(從流的末尾開始定位)。
文件位置指針是一個整數值,指定了從文件的起始位置到指針所在位置的字節數。下面是關於定位 "get" 文件位置指針的實例:
// 定位到 fileObject 的第 n 個字節(假設是 ios::beg)
fileObject.seekg( n );
// 把文件的讀指針從 fileObject 當前位置向後移 n 個字節
fileObject.seekg( n, ios::cur );
// 把文件的讀指針從 fileObject 末尾往回移 n 個字節
fileObject.seekg( n, ios::end );
// 定位到 fileObject 的末尾
fileObject.seekg( 0, ios::end );
關閉文件:
當程序終止時,關閉文件刷新所以流,釋放內存,是每個程序員必備的習慣。
void close();
總結:學習並複習了下c/c++的標準IO和文件IO,這只是冰上的一角。漫漫編程路需要我們不斷的學習與重溫、不斷練習,方可達到水滴石穿效果。