檔案IO操作

chenwr2018發表於2019-03-03

檔案IO操作

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char s_readbuf[100];
char *ADP_NET_GetModuleVer_SW()
{
    FILE *fp = NULL;
    int len;
    fp = fopen("./version", "r");
    if (!fp) {
        printf("fopen error\n");
        return 0;
    }
    fseek(fp, 0, SEEK_END);
    len = ftell(fp);
    rewind(fp);
    fread(s_readbuf, 1, len-1, fp);//len-1 去除換行符
    s_readbuf[len] = '\0';
    fclose(fp);
    fp = NULL;
    return s_readbuf;
}
void main()
{
    char *buf = NULL;

    buf = ADP_NET_GetModuleVer_SW();
    printf("file content: %s\n", buf);
}
複製程式碼

知識點說明

一、fopen

(1)函式原形

FILE * fopen(const char * path, const char * mode);

(2)引數mode

引數mode說明
(3)二進位制和文字模式的區別

  • 在Windows系統中,文字模式下,檔案以"\r\n"代表換行。若以文字模式開啟檔案,並用 fputs 等函式寫入換行符"\n"時,函式會自動在"\n"前面加上"\r"。即實際寫入檔案的是"\r\n"。
  • 在類 Unix/Linux 系統中文字模式下,檔案以"\n"代表換行。所以 Linux 系統中在文字模式和二進位制模式下並無區別。

(4)返回值

檔案順利開啟後,指向該流的檔案指標就會被返回。如果檔案開啟失敗則返回 NULL,並把錯誤程式碼存在 error 中。

(5)注意事項

  • 在定義檔案指標時,要將檔案指標指向空;如 FILE *fp = NULL
  • 在檔案操作完成後,別忘記fclose,否則會造成記憶體洩漏和在下次訪問檔案時出現問題。
  • 檔案關閉後,需要將檔案指標指向空,這樣做會防止出現遊離指標,而對整個工程造成不必要的麻煩;如:fp = NULL

二、fseek

(1)函式原形

int fseek(FILE *stream, long offset, int fromwhere);

(2)引數說明

第一個引數stream為檔案指標 第二個引數offset為偏移量,正數表示正向偏移,負數表示負向偏移 第三個引數origin設定從檔案的哪裡開始偏移,可能取值為:SEEK_CUR、 SEEK_END 或 SEEK_SET

SEEK_SET: 檔案開頭 SEEK_CUR: 當前位置 SEEK_END: 檔案結尾

其中SEEK_SET,SEEK_CUR和SEEK_END依次為0,1和2.

簡言之: fseek(fp,100L,0);把stream指標移動到離檔案開頭100位元組處; fseek(fp,100L,1);把stream指標移動到離檔案當前位置100位元組處; fseek(fp,-100L,2);把stream指標退回到離檔案結尾100位元組處。

(3)返回值

  • 如果執行成功,stream將指向以fromwhere為基準,偏移offset(指標偏移量)個位元組的位置,函式返回0。
  • 如果執行失敗(比如offset超過檔案自身大小),則不改變stream指向的位置,函式返回-1,設定error的值,可以用perror()函式輸出錯誤。

(4)注意事項

  • 檔案指標操作檔案,會直接覆蓋原先的內容。fread fwrite操作都會對檔案指標進行偏移。
  • 實現檔案內容中插入字串,先定位到要插入的檔案指標位置,將之後的內容儲存在快取中,插入目標字串後再把檔案快取的內容新增。
  • 函式 ftell 用於得到檔案位置指標當前位置相對於檔案首的偏移位元組數。配合fseek使用。會計算換行符的長度
  • 計算完檔案長度後,記得rewind(將檔案內部的位置指標重新指向一個流(資料流/檔案)的開頭)。等價於fseek(stream, 0L, SEEK_SET)。

三、fread

(1)函式原形

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

(2)引數說明

buffer 用於接收資料的記憶體地址 size 要讀的每個資料項的位元組數,單位是位元組 count 要讀count個資料項,每個資料項size個位元組. stream 輸入流

(3)返回值

個人理解為返回資料項數

char *ADP_NET_GetModuleVer_SW()
{
    FILE *fp = NULL;
    int len;
    int ret;

    fp = fopen("./version", "r");
    if (!fp) {
        printf("fopen error\n");
        return 0;
    }
    fseek(fp, 0, SEEK_END);
    len = ftell(fp);
    rewind(fp);
    ret = fread(s_readbuf, 1, len-1, fp);//len-1 去除換行符
    printf("len = %d\n", len);
    printf("fread ret = %d\n", ret);
    //fread(s_readbuf, len-1, 1, fp);
    s_readbuf[len] = '\0';
    fclose(fp);
    fp = NULL;
    return s_readbuf;    
}
void main()
{
    char *buf = NULL;
    int ret;
    buf = ADP_NET_GetModuleVer_SW();
    printf("file content: %s\n", buf);
}
複製程式碼

執行結果:

len = 28
fread ret = 27
file content: plt-ec20-0.01
plt-ec20-0.02
複製程式碼

當使用 fread(s_readbuf, 1, len, fp),當len小於fp檔案中實際的長度,fread的返回值為len,當len大於fp檔案中實際的長度。fread的返回值為檔案fp實際的長度。

修改為:ret = fread(s_readbuf, 1, 50, fp);
執行結果:
len = 28
fread ret = 28
file content: plt-ec20-0.01
plt-ec20-0.02

修改為:ret = fread(s_readbuf, 1, 5, fp);
執行結果:
len = 28
fread ret = 5
file content: plt-e
複製程式碼

當使用 fread(s_readbuf, len, 1, fp),這種語句時,個人理解為讀取一個資料項,資料項長度為引數2,當fp檔案長度小於len,則說明沒有讀取完整一個資料項,返回值為0。反之說明已經讀取完整一個資料項,返回值為1。

修改為:ret = fread(s_readbuf, 50, 1, fp);
執行結果:
len = 28
fread ret = 0
file content: plt-ec20-0.01
plt-ec20-0.02

修改為:ret = fread(s_readbuf, len, 1, fp);
執行結果:
len = 28
fread ret = 1
file content: plt-ec20-0.01
plt-ec20-0.02
複製程式碼

4、fwrite

(1)函式原形

size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);

(2)引數說明

  • buffer:是一個指標,對fwrite來說,是要獲取資料的地址;
  • size:要寫入內容的單位元組數;
  • count:要進行寫入size位元組的資料項的個數;
  • stream:目標檔案指標;
  • 返回實際寫入的資料項個數count。

(3)返回值

返回實際寫入的資料塊數目

相關文章