?C++中的文件輸入/輸出(6):一些有用的函數
原作:Ilia Yordanov,?
loobian@cpp-home.com
????
???
tellg() ——
返回一個
int
型數值,它表示“內置指針”的當前位置。此函數僅當你在讀取一個文件時有效。例如:
???
#include <fstream.h>
??? ?
??? void main()
??? {
??? ???
//
假如我們已經在
test_file.txt
中存有了“
Hello
”的內容
???
??? ifstream File("test_file.txt");
??? ?
??? ??? char arr[10];
??? ?
??? ??? File.read(arr,10);
??? ???
??? ???
//
由于
Hello
占
5
個字符,因此這里將返回
5
???
??? cout << File.tellg() << endl;
??? ?
??? ??? File.close();
??? }
???
???
tellp()
——
與
tellg()
有同樣的功能,但它用于寫文件時。總而言之:當我們讀取一個文件,并要知道內置指針的當前位置時,應該使用
tellg()
;當我們寫入一個文件,并要知道內置指針的當前位置時,應該使用
tellp()
.
由于此函數的用法與
tellg()
完全一樣,我就不給出示例代碼了。
???
???
seekp() ——
還記得
seekg()
么?當我在讀取一個文件,并想到達文件中某個特定位置時,就曾使用過它。
seekp()
亦如此,只不過它用于寫入一個文件的時候。例如,假如我在進行文件讀寫,而要定位到當前位置的三個字符之前,則需調用
FileHandle.seekg(-3)
.
但如果我是在寫入一個文件,并且比如我要重寫后
5
個字符的內容,我就必須往回跳轉
5
個字符,因而,我應該使用
FileHandle.seekp(-5)
.
???
??? ignore() ——
使用于讀取文件之時。如果你想略過一定數量的字符,只需使用此函數。實際上,你也可以使用
seekg()
來代替,然而使用
ignore()
有一個優點
——
你可以指定一個特定“界限規則(
delimiter rule
)”,同樣使得
ignore()
在指定的位置停下。函數原型如下:
???
???
istream& ignore( int nCount, delimiter );
???
???
nCount
表示要略過的字符數量,而
delimiter
——
與它的名稱有著同樣的含義:假如你想在文件末尾停下,則可使用
EOF
值傳入,這樣一來此函數就等同于
seekg()
;但該參數還可以使用其他值,例如
‘\n’
這樣可以在換行的同時定位在新行處。下面是示例:
???
#include <fstream.h>
??? ?
??? void main()
??? {
??? ???
//
假設
test_file.txt
中已經存有
"Hello World"
這一內容
???
??? ifstream File("test_file.txt");
??? ?
??? ??? static char arr[10];
??? ?
??? ???
//
假如一直沒有遇到字符
"l"
,則向前定位直到跳過
6
個字符
???
??? //
而如果期間遇到
"l"
,則停止向前,定位在該處
???
??? File.ignore(6,'l');
??? ?
??? ??? File.read(arr,10);
??? ?
??? ??? cout << arr << endl;
//
它將顯示
"lo World!"
??? ?
???
??? File.close();
??? ?
??? }
???
???
getline() ——
雖然前面的章節中我曾提到過這個函數,但還有一些內容我們未曾涉及:此函數不但可用于逐行讀取,而且它還可以設為遇到某個特定字符后停止讀取。下面給出傳遞這一參數的方法:
???
???
getline(array,array_size,delim);
???
???
以下為示例代碼:
???
???
#include <fstream.h>
??? ?
??? void main()
??? {
??? ???
//
假設
test_file.txt
中已經存有
"Hello World"
這一內容
???
??? ifstream File("test_file.txt");
??? ?
??? ??? static char arr[10];
??? ?
??? ???
/*
讀取,直到滿足下面的條件之一:
??? 1
)已經讀取
10
個字符
??? 2
)遇到字母
"o"
??? 3
)出現新一行
???
??? */
???
??? File.getline(arr,10,'o');
??? ?
??? ??? cout << arr << endl;
//
將顯示
"Hell"
???
??? File.close();
??? }
???
???
peek() ——
此函數將返回輸入流文件的下一個字符,但它不移動內置指針。我想你該記得,像
get()
這樣的函數也返回輸入流文件的下一個字符,而與此同時它將移動內置指針。所以當你再次調用
get()
函數的時候,它會返回再下一個字符,而非前面那個。哦,使用
peek()
也會返回字符,但它不會移動“光標”。所以,假如你連續兩次調用
peek()
函數,它會返回同一個字符。考慮以下代碼:
???
???
#include <fstream.h>
??? ?
??? void main()
??? {
??? ???
//
假設
test_file.txt
中已經存有
"Hello World"
這一內容
???
??? ifstream File("test_file.txt");
??? ?
??? ??? char ch;
??? ?
??? ??? File.get(ch);
??? ??? cout << ch << endl;
//
將顯示
"H"
??? ?
??? ??? cout <<??? char(File.peek()) << endl;
//
將顯示
"e"
???
??? cout <<??? char(File.peek()) << endl;
//
將再次顯示
"e"
??? ?
??? ??? File.get(ch);
??? ??? cout << ch << endl;
//
還是顯示
"e"
???
??? File.close();
??? ???
??? }
???
???
順便說一下,我忘了講
——peek()
函數實質上返回的是字符的
ASCII
碼,而非字符本身。因此,假如你想看到字符本身,你得像我在示例中做的那樣進行調用(譯注:即要轉為
char
類型)
。
???
???
_unlink() ——
刪除一個文件。假如你要使用此函數,需要在你的程序中包含
io.h
頭文件。下面是示例代碼:
???
???
#include <fstream.h>
??? #include <io.h>
??? ?
??? void main()
??? {
??? ??? ofstream File;
??? ?
??? ??? File.open("delete_test.txt");
//
創建一個文件
???
??? File.close();
??? ?
??? ??? _unlink("delete_test.txt");
//
刪除這個文件
???
?
??? ???
//
試圖打開此文件,但假如它已不存在
???
??? //
函數將返回一個
ios::failbit
錯誤值
???
??? File.open("delete_test.txt",ios::nocreate);
??? ?
??? ???
//
驗證它是否返回該值
???
??? if(File.rdstate() == ios::failbit)
??? ??? ??? cout << "Error...!\n";
//
耶,成功了
???
???
File.close();
??? ?
??? }
???
???
putback() ——
此函數將返回最后一個所讀取字符,同時將內置指針移動
-1
個字符。換言之,如果你使用
get()
來讀取一個字符后再使用
putback()
,它將為你返回同一個字符,然而同時會將內置指針移動
-1
個字符,所以你再次使用
get()
時,它還是會為你返回同樣的字符。下面是示例代碼:
???
???
#include <fstream.h>
??? ?
??? void main()
??? {
??? ???
//
test_file.txt
應包含內容
"Hello World"
???
??? ifstream File("test_file.txt");
??? ???
??? ??? char ch;
??? ?
??? ??? File.get(ch);
??? ?
??? ??? cout << ch << endl;
//
將顯示
"H"
??? ?
??? ??? File.putback(ch);
??? ??? cout << ch << endl;
//
仍將顯示
"H"
???
???
???
??? File.get(ch);
??? ??? cout << ch << endl;
//
再一次顯示
"H"
??? ?
??? ??? File.close();
??? }
???
???
flush()
——
在處理輸出流文件的時候,你所存入的數據實際上并非立刻寫入文件,而是先放入一個緩沖區中,直到該緩沖區放滿數據之后,這些數據才被存入真正的文件中(在你的磁盤上)。旋即緩沖區會被清空,再重新進行下一輪寫入。
???
但假如你想在緩沖區寫滿之前就將其中的數據寫入磁盤,則使用
flush()
函數。只須像這樣進行調用:
FileHandle.flush()
,這樣緩沖區內的數據將會寫入實際的物理文件,而后緩沖區被清空。
???
再補充一點(高階的)內容:
flush()
函數會調用與相應流緩沖(
streambuf
)相聯系的
sync()
函數(出自
MSDN
)。