close

//本文章為C/C++程式設計研習班課後心得摘要

硬碟(或其他儲存裝置)都只單純是區塊儲存媒體(block storage)並沒有甚麼檔案或目錄的機構存在,而檔案系統(file system)是作業系統提供的功能,檔案系統紀錄了目錄結構、甚麼檔名對應到硬碟上哪些塊空間、硬碟上哪些空間已經被檔案佔用了不可以覆蓋掉。

檔案分為二進位檔案和文字檔案

二進位檔案 (Binary File)

檔案中的一切資料都被當作原始資料。

與文字檔案 (Text file)

檔案中的資料被解讀成可顯示的字元和一些換行或列印控制字元。

 

檔案的操作都必須透過作業系統,分成open、read/write、close。

開啟檔案 (open)

 

告訴作業系統檔案被使用了,請紀錄他的狀態,互斥性的檔案請阻止其他程式使用。

 

讀取, 寫入檔案 (read/write)

 

檔案內容變更了,作業系統請從磁碟中找額外的儲存區塊,寫入中的檔案請阻止其他程式讀取。

 

關閉檔案 (close)

 

告訴作業系統檔案使用結束。

C語言中,開啟、讀寫、關閉檔案函式,把檔案分為文字檔案、2進位檔開啟。

 

二進位檔開啟

標準函式庫的檔案處理函式庫,都在 stdio.h 當中,所以必須 #include <stdio.h>,在當中有一個 FILE 結構體,標準函式庫的函式用它來紀錄已開啟檔案的一切資訊,包括目前的讀取位置,所以要以二進位檔的方式開啟一個檔案以供讀取
//標準函式庫寫在stdio.h中,有用到要宣告 #include <stdio.h>。另外,在stdio.h有個FILE結構體,函式用他來記錄開啟檔案。

FILE *stream =fopen("檔案名稱", "rb");

它傳回一個內部結構體 FILE 的指標,你必須保留這個指標,但是不要去操作它的內容。如果無法開啟檔案(例如檔案不存在)則傳回 NULL,其中的 "rb" 參數指定檔案要以二進位檔模式開啟,你也可以此方式把文字檔當作二進位檔案開啟,然後就可以 fread( ) 函式來讀取內容。

原型: size_t fread( void * buffer,  size_t size, size_t count,  FILE * stream );

參數

  • buffer : 儲存讀取資料的記憶體空間。//有緩衝區的輸出入,輸出入>>緩衝區(buffer)>>磁碟
  • size : 讀取的單位長度,例如下例的 sizeof(int)。
  • count : 讀取的個數,下例只讀取1個整數。
  • stream : 以 fopen( ) 獲得的 FILE * 內部結構體指標。

傳回值:

讀取到的 bytes,如果檔案斷掉可能會少於size*count bytes ( 跟除法原理一樣啦,可以用來判斷檔案是否不完整。

例如讀取一個整數:

原型:fread(&a, sizeof(int), 1, stream);

讀取後 stream 的讀取位置會移動,指向下筆資料。你可以看到 fread( ) 的參數以類似 qsort( ) 的方式描述一個陣列空間,所以也可以用來讀取多筆資料,例如一次讀入 3 個浮點數:

float vec[3];
int readBytes = fread(vec, sizeof(float), 3, stream);
if (readBytes < 12) {  printf("檔案結束!");  }

上例中的 fread( ) 應該讀取到 12 bytes,而且讀取後檔案讀取指標移動 12 bytes,如果不足12表示檔案已結束。你可以 ftell 來獲知目前的讀取位置,它傳回目前已讀取的長度(從檔案開頭算來幾 bytes)。

原型long ftell( FILE * stream );

在結束讀取以後,你應該以 fclose( ) 關閉檔案,告訴作業系統這個檔案已經結束讀取或寫入了。

原型int fclose( FILE * stream ); 

其中的參數 stream 是 fopen( ) 獲得的 FILE * 內部結構體指標,基本上,使用這種方式讀取檔案,你必須明確地知道該檔案的儲存格式,所以通常用於撰寫讀檔或解碼程式。

寫入二進位檔

 

FILE *stream = fopen("檔案名稱", "wb");

 

傳回一個內部結構體 FILE 的指標, "wb" 參數會建立一個空的新檔案,如果該檔案已經存在則會覆蓋掉它。若無法建立檔案(磁碟空間不足或唯讀)則傳回 NULL,如果不想要覆蓋掉原檔案,而是想要在原檔案尾端附加(append)資料,則以 "ab" 模式開啟檔案,但若原檔案不存在則會建立一個空的新檔案。

接著以類似 fread( ) 的方式呼叫 fwrite( ),寫入指定長度的資料到檔案中。

 

原型: size_t fwrite( void * buffer, size_t size, size_t count, FILE * stream );

 

參數

 

  • buffer : 儲存欲寫入資料的記憶體空間。
  • size : 寫入的單位長度,例如下例 sizeof(int)。
  • count : 寫入的個數,下例只寫入1個整數。
  • stream : fopen( ) 獲得的 FILE * 內部結構體指標。

 

傳回值

 

成功寫入的 bytes,如果發生錯誤(例如磁碟已滿)可能會少於 size*count bytes。

 

例如寫入一個整數:

 

fwrite(&a, sizeof(int), 1, stream);

 

完成檔案寫入以後,同樣必須以 fclose( ) 關閉檔案。

 

讀取文字檔案

同樣是以 fopen( ) 來開啟檔案,但是參數改用 "rt"。

開啟以後的檔案讀寫不使用 fread( ) 與 fwrite( ),而是類似前面的主控台輸出入,採用 fgetc( )、fgets( )、fputc( )、fputs( )、fprintf( ) 等等的字元或字串輸出入函式。

也可以把非文字檔當作文字檔開啟,但後續這些函式操作可能都會失敗。

 

FILE *stream =fopen("檔案名稱", “rt”);

 

傳回一個內部結構體 FILE 的指標,若無法開啟檔案(例如檔案不存在)則傳回 NULL。

 

讀取單一字元

原型int fgetc( FILE * stream ); //是不是和 _getch( ) 很像?

例如: int c = fgetc(stream);
參數: stream : fopen( ) 獲得的 FILE * 內部結構體指標。
傳回值: 讀取到的字元,如果已經讀到檔尾則傳回 EOF,也就是整數 -1

 

讀取一行字串

 

原型char * fgets( char * str, int n, FILE * stream ); //是不是和 gets( ) 很像?

例如: fgetc(buffer, 512, stream);

 

參數

 

  • str: 儲存讀取到的文字的字元陣列空間。
  • n: str 的空間大小,避免 fgets( ) 讀取過頭。
  • stream : fopen( ) 獲得的 FILE * 內部結構體指標。

 

傳回值

 

如果讀取不到一行文字則傳回 NULL。

 

#include <stdio.h>

void main(void)
{
    char buffer[256];

    // 嘗試開啟 ReadMe.txt 檔案:
    FILE *stream = fopen("ReadMe.txt", "rt");

    if (stream)
    {
        // 如果檔案開啟成功,以fgets( ) 逐行讀取:
        while(fgets(buffer, 256, stream) != NULL)
        {  printf("%s\n", buffer);  }
//fgets( ) 讀進來的文字不包含換行,所以顯示的時候特別以 printf 加 \n 來顯示之。 // 關閉檔案: fclose(stream); } else { printf("檔案不存在喔!"); } }

 

寫入文字檔

 

FILE *stream =fopen("檔案名稱", "wt");

 

傳回一個內部結構體 FILE 的指標。使用 "wt" 參數會建立一個空的新檔案,如果該檔案已經存在則會覆蓋掉它。使用 "at" 則從該檔案的尾端接著寫入,如果檔案不存在則會建立一個空的新檔案。若無法建立檔案(磁碟空間不足或唯讀)則會傳回 NULL

 

單純寫入一串文字

 

原型: int fputs( const char* s, FILE* stream);// 是不是和 puts( ) 很像只是多了一個 stream 參數?

 

參數

 

  • s: 待寫入的一行文字。
  • stream : fopen( ) 獲得的 FILE * 內部結構體指標。

 

傳回值

 

如果寫入失敗則傳回 EOF

 

格式化地寫入一串文字

 

原型fprintf(FILE* stream,"" ,變數 );//紅色部分和一般printf一樣

二進位檔案操作是記憶體與檔案之間、逐 byte 的原始資料交換。
文字檔案的操作方法則是字串處理與輸出入。
從檔案中獲得的字串必須經過 strtok( ) 切割,atoi( ) 或 atof( ) 轉換為數值資料,才能夠進行運算。

重點整理

  • 檔案的操作模式分為二進位和文字檔兩種。
  • 檔案操作必須經過開啟檔案,讀寫檔案,關閉檔案的程序。
  • 從主控台獲得字元或字串的方式,也有類似的方式從文字檔獲得字元或一行文字。
  • 輸出文字到螢幕的方式,也有類似方式輸出文字到文字檔。

 

 

//補充函式 

 

函數名稱

功能說明

fopen( )

開啟一個檔案//參數有很多種參考註

fclose( )

關閉一個檔案

putc( )

輸出一個字元到檔案

int putc( int ch, FILE *fp );

getc( )

從某一個檔案讀取一個字元

int  getc(FILE  *fp);

fprintf( )

輸出資料至某檔案
//printf( )是列印到螢幕,fprintf是列印到檔案

fscanf( )

從某檔案讀取資料

//scanf( )函數主要用於從鍵盤輸入讀取資料,fscanf是從檔案讀取。
fscanf( fp ,  "……." , ………);

feof( )

測試是否到了檔案結束位置

ferror( )

測試檔案操作是否正常

fseek( )

設定準備讀取檔案資料的位置

rewind( )

將準備讀取檔案資料位置,設定在檔案起始位置

remove( )

檔案的刪除

 

註:


"r":開啟一個文字檔(text),供程式讀取。

"w":開啟一個文字檔(text),供程式將資料寫入此檔案內。如果磁碟內不包含這個檔案,則系統會自行建立。如果磁碟內包含這個檔案,則此檔案內容會被蓋過而消失。

"a":開啟一個文字檔(text),供程式將資料寫入此檔案的末端。如果此檔案不存在,則系統會自行建立此檔案。

"rb":開啟一個二元檔(binary),供程式讀取。

"wb":開啟一個二元檔,供程式將資料寫入此檔案內。如果磁碟內不包含這個檔案,則系統會自行建立這個檔案。如果磁碟內包含這個檔案,此檔案內容會被蓋過而消失。

"ab":開啟一個二元檔(binary),供程式將資料寫入此檔案末端,如果此檔案不存在,則系統會自行建立此檔案。

 

 

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 winage 的頭像
    winage

    winage的部落格

    winage 發表在 痞客邦 留言(0) 人氣()