【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。