Linux C++:標準IO&文件IO

    以前學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,這只是冰上的一角。漫漫編程路需要我們不斷的學習與重溫、不斷練習,方可達到水滴石穿效果。

參考:https://www.runoob.com/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章