1. 程式人生 > >【C++入門筆記】檔案操作

【C++入門筆記】檔案操作

前言

此文是FishC大佬第四堂課的內容小結,學到了很多,來總結一下。

檔案操作

C語言版本

利用C語言編寫一個檔案複製的程式,如下所示。

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char* argv[] )
/*
argc和argv[]
在程式中,main函式有兩個引數,整型變數argc和字元指標陣列argv[]。
argc的含義是程式的引數數量,包含本身。
argv[]的每個指標只想命令列的一個字串,所以argv[]指向字串“copyFile.exe” 
argv[1]指向字串sourceFile,argv[2]只想字串destFile。

*/
{
      FILE *in, *out;	//in和out是我們宣告的兩個檔案指標,它們的型別都是FILE*,分別作為兩個I/O流物件使用。
      int ch;  // char

      if( argc != 3 )
      {
            fprintf( stderr, "輸入形式: copyFile 原始檔名 目標檔名 \n" );
            exit( EXIT_FAILURE );
      }

      if( ( in = fopen( argv[1], "rb") ) == NULL )
		  /*
		  通過fopen()函式我們以二進位制的形式按照可讀/可寫方式開啟兩個檔案
		  並返回兩個檔案指標給in和out
		  */
      {
            fprintf( stderr, "打不開檔案: %s \n", argv[1] );
            exit( EXIT_FAILURE );
			/*
			為了確保檔案成功開啟,我們還對fopen()的返回值進行了檢查,
			如果未成功開啟,我們就向標準錯誤流stderr傳送一條訊息。
			*/
      }

      if( ( out = fopen( argv[2], "wb") ) == NULL )
      {
            fprintf( stderr, "打不開檔案: %s \n", argv[2] );
            fclose( in );                                   // 記得擦屁股
            exit( EXIT_FAILURE );
      }

      while( (ch = getc(in)) != EOF ) // EOF == end of file
		  /*
		  getc()函式一次從輸入流(stdin)讀取一個字元
		  putc()函式把這個字元寫到輸出流(stdout)
		  */
      {
            if( putc( ch, out ) == EOF )
            {
                  break;
            }
      }

      if( ferror( in ) )
      {
            printf("讀取檔案 %s 失敗! \n", argv[1] );
      }

      if( ferror( out ))
      {
            printf("寫入檔案 %s 失敗! \n", argv[2] );
      }

      printf("成功複製1個檔案!\n");

      fclose( in );
      fclose( out );

      return 0;
}

沒什麼好特別說明的,註釋已經寫到了程式當中。

C++版本

基本的檔案讀寫操作:

ifstream in;

in.open("test.txt")

以及

ofstream out;

out.open("test.txt")

以上程式碼在建立一個ifstream和ofstream類的物件時,將檔案的名字傳遞給它們的建構函式。

下面給出一個接收兩個引數的例項:

ifstream in(char* filename,int open_mode)

其中:filename表示檔案的名稱,它是一個字串;open_mode表示開啟模式,其值用來定義以怎麼樣的方式開啟檔案(跟open的引數一樣)

下面給出幾種常見的開啟模式:

ios::in -- 開啟一個可讀取檔案

ios::out -- 開啟一個可寫入檔案

ios::binary -- 以二進位制的形式開啟一個檔案。

ios::app -- 寫入的所有資料將被追加到檔案的末尾。

ios::trunc -- 刪除檔案原來已經存在的內容

ios::nocreate -- 如果要開啟的檔案並不存在,那麼以此引數呼叫open函式將無法進行。

ios::noreplace -- 如果要開啟的檔案已經存在,那麼試圖以此引數呼叫open函式將返回一個錯誤。

如果需要不只是一種開啟方式,而是需要多種開啟模式的話,可以用 OR操作符: |

而為什麼可以使用OR操作符來選擇多種開啟模式呢,來看一段栗子:

#include <fstream>
#include <iostream>

using namespace std;

int main()
{
      fstream fp("test.txt", ios::in | ios::out );
      if( !fp )
      {
            cerr << "開啟檔案失敗!" << endl;
            return 0;
      }

      fp << "IloveFishc.com!";

      static char str[100]; 

      fp.seekg(ios::beg);  // 使得檔案指標指向檔案頭 如果ios::end 則是檔案尾。
      fp >> str;
      cout << str << endl;

      fp.close();

      return 0;
}

其中利用 | 選擇了ios::in 和ios::out 兩種開啟模式,我們首先編譯這段程式,然後右鍵ios::in 選擇轉到定義,可以看到ios_base.h檔案,其中可以看到如下定義:

    typedef _Ios_Openmode openmode;

    /// Seek to end before each write.
    static const openmode app =		_S_app;

    /// Open and seek to end immediately after opening.
    static const openmode ate =		_S_ate;

    /// Perform input and output in binary mode (as opposed to text mode).
    /// This is probably not what you think it is; see
    /// http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt11ch27s02.html
    static const openmode binary =	_S_bin;

    /// Open for input.  Default for @c ifstream and fstream.
    static const openmode in =		_S_in;

    /// Open for output.  Default for @c ofstream and fstream.
    static const openmode out =		_S_out;

    /// Open for input.  Default for @c ofstream.
    static const openmode trunc =	_S_trunc;

以及:

 

  enum _Ios_Openmode 
    { 
      _S_app 		= 1L << 0,
      _S_ate 		= 1L << 1,
      _S_bin 		= 1L << 2,
      _S_in 		= 1L << 3,
      _S_out 		= 1L << 4,
      _S_trunc 		= 1L << 5,
      _S_ios_openmode_end = 1L << 16 
    };

 

可以發現定義成了一個列舉型別,其中1作為long int處理,佔4byte,在此基礎上,將1二進位制左移不同的位數,在使用時進行OR操作的話具有唯一性。

輸入資料合法性檢查

cin物件有幾個專門用來報告其工作情況的成員函式,它們將返回一個真/假值來表明cin的狀態。

-eof() : 如果到達檔案(或輸入)末尾,那麼返回True;

-fail() : 如果cin無法工作,返回True;

-bad() : 如果cin因為比較嚴重的原因(例如記憶體不足)而無法工作,返回True;

-good() : 如果上述情況均未發生,返回True。