C++雜談之關於檔案操作的若干問題

Sunday發表於2014-08-16

原文地址

http://blog.csdn.net/plzhou/article/details/20486305




C++雜談之關於檔案操作的若干問題


一、文字檔案和二進位制檔案

      (1)檔案只是計算機記憶體中二進位制表示的資料在外部儲存介質上的另一種存放方式。檔案通常可以分為二進位制檔案和文字檔案。

      (2)將資料儲存在檔案中時,可以將其儲存為文字格式或二進位制格式。文字格式是指將所有內容(甚至數字)都儲存為文字。例如,以文字格式儲存-2.324216e+07時,將儲存該數字包含的13個字元,這需要將浮點數的計算機內部表示轉換為字元,這正是<<插入操作符完成的工作。另一方面,二進位制格式指的是儲存值的計算機內部表示。也就是說,計算機不是儲存字元,而是儲存這個值的64位double表示。

      (3)對於字元來說,二進位制表示和文字表示都是一樣的,即字元的ASCII碼的二進位制表示。

      (4)對於數字來說,二進位制表示和文字表示有著很大的差別。

      (5)使用二進位制檔案模式時,程式將資料從記憶體傳輸給檔案(反之亦然)時,將不會發生任何隱藏的轉換,而預設的文字模式並非如此。


二、文字方式和二進位制方式

      (1)當按照文字方式向檔案中寫入資料時,一旦遇到“換行”字元(ASCII碼為10),則會轉換為“回車——換行”(ASCII碼分別為13、10)。在讀取檔案時,一旦遇到“回車——換行”的組合(連續的ASCII碼為13、10),則會轉換為換行字元(ASCII碼為10)。

      (2)當按照二進位制方式向檔案中寫入資料時,則會將資料在記憶體中的儲存形式原樣輸出到檔案中。

      (3)由於文字方式和二進位制方式在讀取和寫入資料時的差異,所以在寫入和讀取檔案時要保持一致。如果採用文字方式寫入,應採用文字方式讀取;如果採用二進位制方式寫入資料,在讀取時也應採用二進位制方式。否則就會出現問題。

      (4)不管是文字檔案還是而二進位制檔案,如果統一採用二進位制方式進行寫入和讀取,則是不會出錯的。因為這種讀取和寫入時嚴格按照一個位元組一個位元組進行的。

      注:讀者一定要注意文字檔案和二進位制檔案,文字方式和二進位制方式之間的區別,不要混淆。不管是文字檔案還是二進位制檔案,都可以採用二進位制方式或文字方式開啟,然後進行寫入或讀取。但是,對於二進位制檔案來說,如果以文字方式讀取時,可能出現一些問題。

      文字檔案和二進位制檔案,文字方式和二進位制方式之間是沒有關係的,他們描述了檔案的不同方面。前者描述了檔案的儲存方式,後者描述了檔案的開啟方式(換行符有區別)。


三、格式化操作和非格式化操作

 

C

C++

格式化操作

實現函式:fscanf , fprintf,sscanf,sprintf

實現方式:利用格式字串進行相應格式的轉換

實現函式:<< , >>

實現方式:是通過對插入和提取運算子的過載實現的

讀取時(數值):將字串轉換成數值

寫入時(數值):經數值轉化為字串形式

非格式化操作

實現函式:fread , fwrite

實現方式:以二進位制方式直接寫入一定位元組長度的資料

實現函式:.read ,  .write

實現方式:以二進位制方式直接寫入一定位元組長度的資料

讀取寫入:數值和字串時都不會進行任何的轉換

        格式化操作和非格式化操作主要區別在於對讀取寫入資料的操作,前者會對資料進行相應的格式化,而後者原樣輸入(只是相對來說,其實是有變化的,如果記憶體單元式char型別,則不會變化,若是short,int等型別,則會進行相應的變化,具體如下說明)。 

 

注:關於fread、fwrite和.read、.write的說明:

      (1)(在intel系統中,最低位在前,最高位在後),當使用fwrite,.write寫入資料時,char型別直接寫入,short,int,long型別在會倒置,即最低位在前,最高位在後。例如:十六進位制:00 01 00 00 (即:00 00 01 00 也就是2的8次方 ),十進位制:256. 

      當使用fread,.read讀取資料時,char型別直接讀入,short,int,long型別會將檔案中的資料倒置,恢復到正常的順序(是寫入的逆過程),以便正確的讀入資料。

      (2)fread(const void* buf,int size,int count,FILE* file)

                fwrite(const void*buf,int size,int count,FILE* file)

      按照上述規則進行讀取寫入資料,讀寫資料大小為size*count。當分配的記憶體為結構體或者陣列時,只要讀寫的資料長度正確,則函式會根據資料中具體的元素的資料型別應用上述規則。

      總結:如果記憶體單元式char型別,則不會變化,若是shortint等型別,則會進行相應的變化,(造成的原因:IntelMorola系統的儲存方式區別:Little EndianBig Indian)

      (1)讀取示例

            十六進位制: 00 01 00 02 0003

            讀取函式:

            short buf[3];

            fread((const void*)buf,2,3,fp);

            for(int i=0;i<3;i++)

            cout<<buf[i]<<endl;

            則顯示結果為:256,512,768

      (2)寫入示例

            struct test{char a;shot b;intc;long d}

            test data={‘a’,1,2,3};

            fwrite((constvoid*)&data,1,sizeof(data),fp)

            則檔案的十六進位制顯示為:61 01 00 02 00 00 00 03 00 00 00


四、文字檔案,二進位制檔案中的格式化、非格式化操作

 

操作

實現

文字檔案

讀寫數值:

(可以通過格式     化和非格式化實現)

格式化操作:fscanf,fprint;<<,>>

將字串形式的數值直接轉化為相應的資料型別的資料,讀取長度:從第一個非空格開始直到與數字不相同的字元為止

示例:檔案中有:1234.5678

C:

double val;

fscanf(fp,”%lf”,&val);

C++:

double val;

fp>>val;

非格式化操作:fread,fprint; .read, .write(注意上述說明,最好採用char元素記憶體,則不會存在變化)

首先先將檔案中的數值以字串的形式完整讀入,然後再將字串轉換成相應資料型別的資料,讀取長度:自己指定

示例:檔案中有:1234.5678

char buf[9];

fread(buf,1,8,fp);

double val;

sscanf(buf,”%lf”,&val);

讀取字串:

格式化操作和非格式化操作都是相同的,不會對字串進行相應的轉化,一般使用fgets,.gets讀取字串,主要是可以指定讀取長度。直接用>>,將讀入全部,因為文字檔案都是字串。

二進位制檔案

讀取數值:

由於儲存時直接儲存數值的二進位制形式,所以不需要進行相應的轉化,只需知道資料的格式。

只能通過非格式化操作實現

讀取字串:

檔案直接儲存字串的ASCII碼值得二進位制形式,所以直接讀取一定長度的字串即可。

      文字檔案和二進位制檔案,文字方式和二進位制方式,以及格式化操作和非格式化操作之間是沒有嚴格的關係的,他們描述了檔案的不同方面。前者描述了檔案的儲存方式,中間者描述了檔案的開啟方式,而後者描述了在對檔案讀取寫入資料時對資料(尤其是數值)的處理方式。

  


相關文章