欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解C++編程中對二進制文件的讀寫操作

 更新時間:2015年09月24日 18:10:35   投稿:goldensun  
這篇文章主要介紹了C++編程中對二進制文件的讀寫操作,是C++入門學習中的基礎知識,需要的朋友可以參考下

二進制文件不是以ASCII代碼存放數(shù)據(jù)的,它將內(nèi)存中數(shù)據(jù)存儲形式不加轉(zhuǎn)換地傳送到磁盤文件,因此它又稱為內(nèi)存數(shù)據(jù)的映像文件。因為文件中的信息不是字符數(shù)據(jù),而是字節(jié)中的二進制形式的信息,因此它又稱為字節(jié)文件。

對二進制文件的操作也需要先打開文件,用完后要關(guān)閉文件。在打開時要用ios::binary指定為以二進制形式傳送和存儲。二進制文件除了可以作為輸入文件或輸出文件外,還可以是既能輸入又能輸出的文件。這是和ASCII文件不同的地方。
用成員函數(shù)read和write讀寫二進制文件

對二進制文件的讀寫主要用istream類的成員函數(shù)read和write來實現(xiàn)。這兩個成員函數(shù)的原型為

  istream& read(char *buffer,int len);
  ostream& write(const char * buffer,int len);


字符指針buffer指向內(nèi)存中一段存儲空間。len是讀寫的字節(jié)數(shù)。調(diào)用的方式為:

  a. write(p1,50);
  b. read(p2,30);


上面第一行中的a是輸出文件流對象,write函數(shù)將字符指針p1所給出的地址開始的50個字節(jié)的內(nèi)容不加轉(zhuǎn)換地寫到磁盤文件中。在第二行中,b是輸入文件流對象,read 函數(shù)從b所關(guān)聯(lián)的磁盤文件中,讀入30個字節(jié)(或遇EOF結(jié)束),存放在字符指針p2所指的一段空間內(nèi)。

[例] 將一批數(shù)據(jù)以二進制形式存放在磁盤文件中。

#include <fstream>
using namespace std;
struct student
{
  char name[20];
  int num;
  int age;
  char sex;
};
int main( )
{
  student stud[3]={"Li",1001,18,'f',"Fun",1002,19,'m',"Wang",1004,17,'f'};
  ofstream outfile("stud.dat",ios::binary);
  if(!outfile)
  {
   cerr<<"open error!"<<endl;
   abort( );//退出程序
  }
  for(int i=0;i<3;i++)
   outfile.write((char*)&stud[i],sizeof(stud[i]));
   outfile.close( );
  return 0;
}

用成員函數(shù)write向stud.dat輸出數(shù)據(jù),從前面給出的write函數(shù)的原型可以看出: 第1個形參是指向char型常變量的指針變量buffer,之所以用const聲明,是因為不允許通過指針改變其指向數(shù)據(jù)的值。形參要求相應的實參是字符指針或字符串的首地址?,F(xiàn)在要將結(jié)構(gòu)體數(shù)組的一個元素(包含4個成員)一次輸出到磁盤文件stud.dat。&tud[i] 是結(jié)構(gòu)體數(shù)組第i個元素的首地址,但這是指向結(jié)構(gòu)體的指針,與形參類型不匹配。因此 要用(char *)把它強制轉(zhuǎn)換為字符指針。第2個參數(shù)是指定一次輸出的字節(jié)數(shù)。sizeof (stud[i])的值是結(jié)構(gòu)體數(shù)組的一個元素的字節(jié)數(shù)。調(diào)用一次write函數(shù),就將從&tud[i]開始的結(jié)構(gòu)體數(shù)組的一個元素輸出到磁盤文件中,執(zhí)行3次循環(huán)輸出結(jié)構(gòu)體數(shù)組的3個元素。

其實可以一次輸出結(jié)構(gòu)體數(shù)組的個元素,將for循環(huán)的兩行改為以下一行:

  outfile.write((char*)&stud[0],sizeof(stud));


執(zhí)行一次write函數(shù)即輸出了結(jié)構(gòu)體數(shù)組的全部數(shù)據(jù)。

abort函數(shù)的作用是退出程序,與exit作用相同。

可以看到,用這種方法一次可以輸出一批數(shù)據(jù),效率較高。在輸出的數(shù)據(jù)之間不必加入空格,在一次輸出之后也不必加回車換行符。在以后從該文件讀入數(shù)據(jù)時不是靠空格作為數(shù)據(jù)的間隔,而是用字節(jié)數(shù)來控制。

[例] 將剛才以二進制形式存放在磁盤文件中的數(shù)據(jù)讀入內(nèi)存并在顯示器上顯示。

#include <fstream>
using namespace std;
struct student
{
  string name;
  int num;
  int age;
  char sex;
};
int main( )
{
  student stud[3];
  int i;
  ifstream infile("stud.dat",ios::binary);
  if(!infile)
  {
   cerr<<"open error!"<<endl;
   abort( );
  }
  for(i=0;i<3;i++)
  infile.read((char*)&stud[i],sizeof(stud[i]));
  infile.close( );
  for(i=0;i<3;i++)
  {
   cout<<"NO."<<i+1<<endl;
   cout<<"name:"<<stud[i].name<<endl;
   cout<<"num:"<<stud[i].num<<endl;;
   cout<<"age:"<<stud[i].age<<endl;
   cout<<"sex:"<<stud[i].sex<<endl<<endl;
  }
  return 0;
}

運行時在顯示器上顯示:

NO.1
name: Li
num: 1001
age: 18
sex: f

NO.2
name: Fun
num: 1001
age: 19
sex: m

NO.3
name: Wang
num: 1004
age: 17
sex: f

請思考,能否一次讀入文件中的全部數(shù)據(jù),如:

  infile.read((char*)&stud[0],sizeof(stud));

答案是可以的,將指定數(shù)目的字節(jié)讀入內(nèi)存,依次存放在以地址&tud[0]開始的存儲空間中。要注意讀入的數(shù)據(jù)的格式要與存放它的空間的格式匹配。由于磁盤文件中的數(shù)據(jù)是從內(nèi)存中結(jié)構(gòu)體數(shù)組元素得來的,因此它仍然保留結(jié)構(gòu)體元素的數(shù)據(jù)格式?,F(xiàn)在再讀入內(nèi)存,存放在同樣的結(jié)構(gòu)體數(shù)組中,這必然是匹配的。如果把它放到一個整型數(shù)組中,就不匹配了,會出錯。
與文件指針有關(guān)的流成員函數(shù)

在磁盤文件中有一個文件指針,用來指明當前應進行讀寫的位置。在輸入時每讀入 一個宇節(jié),指針就向后移動一個字節(jié)。在輸出時每向文件輸出一個字節(jié),指針就向后移動 一個字節(jié),隨著輸出文件中字節(jié)不斷增加,指針不斷后移。對于二進制文件,允許對指針進行控制,使它按用戶的意圖移動到所需的位置,以便在該位置上進行讀寫。文件流提供 一些有關(guān)文件指針的成員函數(shù)。為了查閱方便,將它們歸納為下表:

幾點說明:
1) 這些函數(shù)名的第一個字母或最后一個字母不是g就是p。帶 g的是用于輸入的函數(shù)(g是get的第一個字母,以g作為輸入的標識,容易理解和記憶), 帶p的是用于輸出的函數(shù)(P是put的第一個字母,以P作為輸出的標識)。例如有兩個 tell 函數(shù),tellg用于輸入文件,tellp用于輸出文件。同樣,seekg用于輸入文件,seekp用于輸出文件。以上函數(shù)見名知意,一看就明白,不必死記。

如果是既可輸入又可輸出的文件,則任意用seekg或seekp。

2) 函數(shù)參數(shù)中的“文件中的位置”和“位移量”已被指定為long型整數(shù),以字節(jié)為單位。“參照位置”可以是下面三者之一:
    ios::beg  文件開頭(beg是begin的縮寫),這是默認值。
    ios::cur  指針當前的位置(cur是current的縮寫)。
    ios::end  文件末尾。
它們是在ios類中定義的枚舉常量。舉例如下:
    infile.seekg(100);  //輸入文件中的指針向前移到字節(jié)位置
    infile.seekg(-50,ios::cur);  //輸入文件中的指針從當前位置后移字節(jié)
    outfile.seekp(-75,ios::end);  //輸出文件中的指針從文件尾后移字節(jié)
隨機訪問二進制數(shù)據(jù)文件

一般情況下讀寫是順序進行的,即逐個字節(jié)進行讀寫。但是對于二進制數(shù)據(jù)文件來說,可以利用上面的成員函數(shù)移動指針,隨機地訪問文件中任一位置上的數(shù)據(jù),還可以修改文件中的內(nèi)容。

[例] 有個學生的數(shù)據(jù),要求:
把它們存到磁盤文件中;
將磁盤文件中的第,3,5個學生數(shù)據(jù)讀入程序,并顯示出來;
將第個學生的數(shù)據(jù)修改后存回磁盤文件中的原有位置。
從磁盤文件讀入修改后的個學生的數(shù)據(jù)并顯示出來。

要實現(xiàn)以上要求,需要解決個問題:
由于同一磁盤文件在程序中需要頻繁地進行輸入和輸出,因此可將文件的工作方式指定為輸入輸出文件,即ios::in|ios::out|ios::binary。
正確計算好每次訪問時指針的定位,即正確使用seekg或seekp函數(shù)。
正確進行文件中數(shù)據(jù)的重寫(更新)。

可寫出以下程序:

#include <fstream>
using namespace std;
struct student
{
  int num;
  char name[20];
  float score;
};
int main( )
{
  student stud[5]={1001,"Li",85,1002,"Fun",97.5,1004,"Wang",54,1006,"Tan",76.5,1010,"ling",96};
  fstream iofile("stud.dat",ios::in|ios::out|ios::binary);
  //用fstream類定義輸入輸出二進制文件流對象iofile
  if(!iofile)
  {
   cerr<<"open error!"<<endl;
   abort( );
  }
  for(int i=0;i<5;i++) //向磁盤文件輸出個學生的數(shù)據(jù)
   iofile.write((char *)&stud[i],sizeof(stud[i]));
  student stud1[5]; //用來存放從磁盤文件讀入的數(shù)據(jù)
  for(int i=0;i<5;i=i+2)
  {
   iofile.seekg(i*sizeof(stud[i]),ios::beg); //定位于第,2,4學生數(shù)據(jù)開頭
   //先后讀入個學生的數(shù)據(jù),存放在stud1[0],stud[1]和stud[2]中
   iofile.read((char *)&stud1[i/2],sizeof(stud1[0]));
   //輸出stud1[0],stud[1]和stud[2]各成員的值
   cout<<stud1[i/2].num<<" "<<stud1[i/2].name<<" "<<stud1[i/2].score<<endl;
  }
  cout<<endl;
  stud[2].num=1012; //修改第個學生(序號為)的數(shù)據(jù)
  strcpy(stud[2].name,"Wu");
  stud[2].score=60;
  iofile.seekp(2*sizeof(stud[0]),ios::beg); //定位于第個學生數(shù)據(jù)的開頭
  iofile.write((char *)&stud[2],sizeof(stud[2])); //更新第個學生數(shù)據(jù)
  iofile.seekg(0,ios::beg); //重新定位于文件開頭
  for(int i=0;i<5;i++)
  {
   iofile.read((char *)&stud[i],sizeof(stud[i])); //讀入個學生的數(shù)據(jù)
   cout<<stud[i].num<<" "<<stud[i].name<<" "<<stud[i].score<<endl;
  }
  iofile.close( );
  return 0;
}

運行情況如下:

1001 Li 85(第個學生數(shù)據(jù))
1004 Wang 54    (第個學生數(shù)據(jù))
1010 ling 96    (第個學生數(shù)據(jù))

1001 Li 85     (輸出修改后個學生數(shù)據(jù))
1002 Fun 97.5
1012 Wu 60     (已修改的第個學生數(shù)據(jù))
1006 Tan 76.5
1010 ling 96

本程序也可以將磁盤文件stud.dat先后定義為輸出文件和輸入文件,在結(jié)束第一次的輸出之后關(guān)閉該文件,然后再按輸入方式打開它,輸入完后再關(guān)閉它,然后再按輸出方式打開,再關(guān)閉,再按輸入方式打開它,輸入完后再關(guān)閉。顯然這是很煩瑣和不方便的。 在程序中把它指定為輸入輸出型的二進制文件。這樣,不僅可以向文件添加新的數(shù)據(jù)或讀入數(shù)據(jù),還可以修改(更新)數(shù)據(jù)。利用這些功能,可以實現(xiàn)比較復雜的輸入輸出任務。

請注意,不能用ifstream或ofstream類定義輸入輸出的二進制文件流對象,而應當用fstream類。

相關(guān)文章

  • C語言實現(xiàn)手寫Map(數(shù)組+鏈表+紅黑樹)的示例代碼

    C語言實現(xiàn)手寫Map(數(shù)組+鏈表+紅黑樹)的示例代碼

    這篇文章主要為大家詳細介紹了如何利用C語言實現(xiàn)手寫Map(數(shù)組+鏈表+紅黑樹),文中的示例代碼講解詳細,對我們學習有一定借鑒價值,需要的可以參考一下
    2022-09-09
  • C++有限狀態(tài)機實現(xiàn)詳解

    C++有限狀態(tài)機實現(xiàn)詳解

    這篇文章主要為大家詳細介紹了C++有限狀態(tài)機的相關(guān)資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C語言中send()函數(shù)和sendto()函數(shù)的使用方法

    C語言中send()函數(shù)和sendto()函數(shù)的使用方法

    這篇文章主要介紹了C語言中send()函數(shù)和sendto()函數(shù)的使用方法,是C語言入門學習中的基礎知識,需要的朋友可以參考下
    2015-09-09
  • boost.asio框架系列之定時器Timer

    boost.asio框架系列之定時器Timer

    這篇文章介紹了boost.asio框架系列之定時器Timer,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • 關(guān)于Visual Studio無法打開源文件

    關(guān)于Visual Studio無法打開源文件"stdio.h"問題

    這篇文章主要介紹了關(guān)于Visual Studio無法打開源文件"stdio.h"問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Cocos2d-x UI開發(fā)之文本類使用實例

    Cocos2d-x UI開發(fā)之文本類使用實例

    這篇文章主要介紹了Cocos2d-x學習筆記之文本類,文本類是UI開發(fā)中經(jīng)常使用的,本文用詳細的代碼注釋講解了文本類的使用,需要的朋友可以參考下
    2014-09-09
  • C語言中字母大小寫轉(zhuǎn)化簡單示例

    C語言中字母大小寫轉(zhuǎn)化簡單示例

    在C語言中,有時候我們遇到這樣的考題,將c語言大寫字母轉(zhuǎn)化為小寫字母,下面這篇文章主要給大家介紹了關(guān)于C語言中字母大小寫轉(zhuǎn)化的相關(guān)資料,文中介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • 在C++中自定義宏的簡單方法

    在C++中自定義宏的簡單方法

    這篇文章主要介紹了在C++中自定義宏的簡單方法,作者建議使用類似定義函數(shù)一樣的方法來定義宏,需要的朋友可以參考下
    2015-07-07
  • c/c++ 利用sscanf進行數(shù)據(jù)拆分操作

    c/c++ 利用sscanf進行數(shù)據(jù)拆分操作

    這篇文章主要介紹了c/c++ 利用sscanf進行數(shù)據(jù)拆分操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • C語言代碼詳細描述順序線性表

    C語言代碼詳細描述順序線性表

    這篇文章主要用代碼介紹了C語言線性表的順序線性表,對于學習數(shù)據(jù)結(jié)構(gòu)與算法的朋友很有參考借鑒價值,需要的朋友可以參考下
    2021-09-09

最新評論