如果文件的每一個字節中均以ASCII代碼形式存放數據,即一個字節存放一個字符,這個文件就是ASCII文件(或稱字符文件)。程序可以從ASCII文件中讀入若干個字符,也可以向它輸出一些字符。
對ASCII文件的讀寫操作可以用以下兩種方法:
1) 用流插入運算符“<<”和流提取運算符“>>”輸入輸出標准類型的數據。“<<”和“ >>”都巳在iostream中被重載為能用於ostream和istream類對象的標准類型的輸入輸出。由於ifstream和ofstream分別是ostream和istream類的派生類(詳情請見:與C++輸入輸出有關的類和對象),因此它們從ostream和istream類繼承了公用的重載函數,所以在對磁盤文件的操作中,可以通過文件流對象和流插入運算符“<<”及流提取運算符“>>”實現對磁盤 文件的讀寫,如同用cin、cout和<<、>>對標准設備進行讀寫一樣。
2) 用文件流的put、get、geiline等成員函數進行字符的輸入輸出,前面已介紹,請查看:用C++流成員函數put輸出單個字符、C++ get()函數讀入一個字符和C++ getline()函數讀入一行字符。
[例13.11] 有一個整型數組,含個元素,從鍵盤輸入個整數給數組,將此數組送到磁盤文件中存放。
#include <fstream>
using namespace std;
int main( )
{
int a[10];
ofstream outfile("f1.dat",ios::out);//定義文件流對象,打開磁盤文件"f1.dat"
if(!outfile) //如果打開失敗,outfile返回值
{
cerr<<"open error!"<<endl;
exit(1);
}
cout<<"enter 10 integer numbers:"<<endl;
for(int i=0;i<10;i++)
{
cin>>a[i];
outfile<<a[i]<<" ";
} //向磁盤文件"f1.dat"輸出數據
outfile.close(); //關閉磁盤文件"f1.dat"
return 0;
}
運行情況如下:
enter 10 integer numbers:
1 3 5 2 4 6 10 8 7 9 ↙
對程序的幾點說明:
1) 程序中用#indude命令包含了頭文件fstream,這是由於在程序中用到文件流類 ofstream,而ofstream是在頭文件fstream中定義的。有人可能會提出:程序中用到cout, 為什麼沒有包含iostream頭文件?這是由於在頭文件fstream中包含了頭文件iostream, 因此,包含了頭文件fstream就意味著已經包含了頭文件iostream,不必重復(當然,多寫 一行#include <iostream > 也不出錯)。
2) 參數 ios::out 可以省寫。 如不寫此項,則默認為ios::out。下面兩種寫法等價:
ofstream outfile("f1.dat", ios::out);
ofstream outfile("f1.dat");
(3) 系統函數exit用來結束程序運行。exit的參數為任意整數,可用0,1或其他整數。由於用了exit函數,某些老版本的C ++要求包含頭文件stdlib.h,而在新版本的C++(如 GCC)則不要求此包含。
4) 在程序中用“cin>>”從鍵盤逐個讀入10個整數,每讀入一個就將該數向磁盤文件輸出,輸出的語句為:
outfile<<a[i]<<" ";
可以看出,用法和向顯示器輸出是相似的,只是把標准輸出流對象cout換成文件輸出流對象outfile而已。由於是向磁盤文件輸出,所以在屏幕上看不到輸出結果。
請注意:在向磁盤文件輸出一個數據後,要輸出一個(或幾個)空格或換行符,以作為數據間的分隔,否則以後從磁盤文件讀數據時,10個整數的數字連成一片無法區分。
[例13.12] 從例13.11建立的數據文件f1.dat中讀入個整數放在數組中,找出並輸出個數中的最大者和它在數組中的序號。
#include <fstream>
using namespace std;
int main( )
{
int a[10],max,i,order;
//定義輸入文件流對象,以輸入方式打開磁盤文件f1.dat
ifstream infile("f1.dat",ios::in|ios::nocreate);
if(!infile)
{
cerr<<"open error!"<<endl;
exit(1);
}
for(i=0;i<10;i++)
{
infile>>a[i]; //從磁盤文件讀入10個整數,順序存放在a數組中
cout<<a[i]<<" "; //在顯示器上順序顯示10個數
}
cout<<endl;
max=a[0];
order=0;
for(i=1;i<10;i++)
if(a[i]>max)
{
max=a[i]; //將當前最大值放在max中
order=i; //將當前最大值的元素序號放在order中
}
cout<<"max="<<max<<endl<<"order="<<order<<endl;
infile.close();
return 0;
}
運行情況如下:
1 3 5 2 4 6 10 8 7 9 (在磁盤文件中存放的個數)
max=10 (最大值為)
order=6 (最大值是數組中序號為的元素)
可以看到:文件f1.dat在例13.11中作為輸出文件,在例13.12中作為輸入文件。 一個磁盤文件可以在一個程序中作為輸入文件,而在另一個程序中作為輸出文件,在不同 的程序中可以有不同的工作方式。甚至在同一個程序中先後以不同方式打開,如先以輸出方式打開,接收從程序輸出的數據,然後關閉它,再以輸入方式打開,程序可以從中讀取數據。
[例13.13] 從鍵盤讀入一行字符,把其中的字母字符依次存放在磁盤文件f2.dat中。再把它從磁盤文件讀入程序,將其中的小寫字母改為大寫字母,再存入磁盤文件f3.dat。
#include <fstream>
using namespace std;
// save_to_file函數從鍵盤讀入一行字符,並將其中的字母存入磁盤文件
void save_to_file( )
{
ofstream outfile("f2.dat"); //定義輸出文件流對象outfile,以輸出方式打開磁盤文件f2.dat
if(!outfile)
{
cerr<<"open f2.dat error!"<<endl;
exit(1);
}
char c[80];
cin.getline(c,80); //從鍵盤讀入一行字符
for(int i=0;c[i]!=0;i++) //對字符逐個處理,直到遇'/0'為止
if(c[i]>=65 && c[i]<=90||c[i]>=97 && c[i]<=122) //如果是字母字符
{
outfile.put(c[i]); //將字母字符存入磁盤文件f2.dat
cout<<c[i]; //同時送顯示器顯示
}
cout<<endl;
outfile.close(); //關閉f2.dat
}
//從磁盤文件f2.dat讀入字母字符,將其中的小寫字母改為大寫字母,再存入f3.dat
void get_from_file()
{
char ch;
//定義輸入文件流outfile,以輸入方式打開磁盤文件f2.dat
ifstream infile("f2.dat",ios::in|ios::nocreate);
if(!infile)
{
cerr<<"open f2.dat error!"<<endl;
exit(1);
}
ofstream outfile("f3.dat");
//定義輸出文件流outfile,以輸出方式打開磁盤文件f3.dat
if(!outfile)
{
cerr<<"open f3.dat error!"<<endl;
exit(1);
}
while(infile.get(ch)) //當讀取字符成功時執行下面的復合語句
{
if(ch>=97 && ch<=122) //判斷ch是否為小寫字母
ch=ch-32; //將小寫字母變為大寫字母
outfile.put(ch); //將該大寫字母存入磁盤文件f3.dat
cout<<ch; //同時在顯示器輸出
}
cout<<endl;
infile.close(); //關閉磁盤文件f2.dat
outfile.close(); //關閉磁盤文件f3.dat
}
int main( )
{
save_to_file( ); //調用save_to_file( ),從鍵盤讀入一行字符並將其中的字母存入磁盤文件f2.dat
get_from_file( ); //調用get_from_file(),從f2.dat讀入字母字符,改為大寫字母,再存入f3.dat
return 0;
}
運行情況如下:
New Beijing, Great Olypic, 2008, China.↙
NewBeijingGreatOlypicChina(將字母寫入磁盤文件f2.dat,同時在屏幕顯示)
NEWBEIJINGGREATOLYPICCHINA (改為大寫字母)
本程序用了文件流的put、get、getline等成員函數實現輸入和輸出,用成員函數inline從鍵盤讀入一行字符,調用函數的形式是cin.inline(c, 80) 在從磁盤文件讀一個字符時用infile.get(ch)。可以看到二者的使用方法是一樣的, cin和infile都是istream類派生類的對象,它們都可以使用istream類的成員函數。二者的區別只在於:對標准設備顯示器輸出時用cin,對磁盤文件輸出時用文件流對象。
磁盤文件f3.dat的內容雖然是ASCII字符,但人們是不能直接看到的,如果想從顯示器上觀看磁盤上ASCII文件的內容,可以采用以下兩個方法:
1) 在DOS環境下用TYPE命令,如
D:\\C++>TYPE f3.dat↙(假設當前目錄是D:\\C++ )
在顯示屏上會輸出
NEWBEIJINGGREATOLYPICCHINA
如果用GCC編譯環境,可選擇File菜單中的DOS Shell菜單項,即可進入DOS環境。想從DOS返回GCC主窗口,從鍵盤輸入exit即可。
2) 編一程序將磁盤文件內容讀入內存,然後輸出到顯示器。可以編一個專用函數。
#include <fstream>
using namespace std;
void display_file(char *filename)
{
ifstream infile(filename,ios::in|ios::nocreate);
if(!infile)
{
cerr<<"open error!"<<endl;
exit(1);
}
char ch;
while(infile.get(ch))
cout.put(ch);
cout<<endl;
infile.close();
}
// 然後在調用時給出文件名即可
int main( )
{
display_file("f3.dat");//將f3.dat的入口地址傳給形參filename
return 0;
}
運行時輸出f3.dat中的字符:
NEWBEIJINGGREATOLYPICCHINA