最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言文件操作詳解以及詳細步驟

 更新時間:2022年06月17日 09:48:08   作者:zjruiiiiii  
文件(file)一般指存儲在外部介質(zhì)上數(shù)據(jù)的集合,比如我們經(jīng)常使用的.txt,?.bmp,?jpg.?.exe,.rmvb等等,下面這篇文章主要給大家介紹了關(guān)于C語言文件操作的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下

一、為什么使用文件?

當(dāng)我們在編寫一個項目的時候,自然而然想到要把之前寫入的數(shù)據(jù)保存起來。而只有我們自己選擇刪除數(shù)據(jù)的時候,數(shù)據(jù)才不復(fù)存在。這就涉及到了數(shù)據(jù)持久化的問題,我們一般數(shù)據(jù)持久化的方法有,把數(shù)據(jù)存放在磁盤文件、存放到數(shù)據(jù)庫等方式。此處我們就講到如何將數(shù)據(jù)放入到磁盤文件當(dāng)中。

二、什么是文件?

磁盤上的文件就是文件。例如電腦當(dāng)中的C盤內(nèi)放入的文件夾內(nèi)的內(nèi)容就是文件。但是在程序設(shè)計中,我們一般談的文件有兩種:程序文件、數(shù)據(jù)文件(從文件功能的角度來分類的)。

1.程序文件

包括源程序文件(后綴為.c),目標文件(windows環(huán)境后綴為.obj),可執(zhí)行程序(windows環(huán)境后綴為.exe)。

2.數(shù)據(jù)文件

文件的內(nèi)容不一定是程序,而是程序運行時讀寫的數(shù)據(jù),比如程序運行需要從中讀取數(shù)據(jù)的文件,或者輸出內(nèi)容的文件。

此篇博客討論的大部分都是數(shù)據(jù)文件。因為我們要學(xué)會如何將文件中的數(shù)據(jù)輸入到內(nèi)存中和如何將程序中的數(shù)據(jù)輸出到文件當(dāng)中。在以前各章所處理數(shù)據(jù)的輸入輸出都是以終端為對象的,即從終端的鍵盤輸入數(shù)據(jù),運行結(jié)果顯示到顯示器上。其實有時候我們會把信息輸出到磁盤上,當(dāng)需要的時候再從磁盤上把數(shù)據(jù)讀取到內(nèi)存中使用,這里處理的就是磁盤上文件。

3.文件名

一個文件要有一個唯一的文件標識,以便用戶識別和引用。

文件名包含3部分:文件路徑+文件名主干+文件后綴

例如: c:\code\test.txt

為了方便起見,文件標識常被稱為文件名。

三、文件的打開和關(guān)閉

1.文件指針

緩沖文件系統(tǒng)中,關(guān)鍵的概念是“文件類型指針”,簡稱**“文件指針”**。

每個被使用的文件都在內(nèi)存中開辟了一個相應(yīng)的文件信息區(qū),用來存放文件的相關(guān)信息(如文件的名字,文件狀態(tài)及文件當(dāng)前的位置等)。這些信息是保存在一個結(jié)構(gòu)體變量中的。該結(jié)構(gòu)體類型是有系統(tǒng)聲明的,取名FILE。

例如,VS2013編譯環(huán)境提供的 stdio.h 頭文件中有以下的文件類型申明:

struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
       };
typedef struct _iobuf FILE;
FILE* pf;//文件指針變量

不同的C編譯器的FILE類型包含的內(nèi)容不完全相同,但是大同小異。

每當(dāng)打開一個文件的時候,系統(tǒng)會根據(jù)文件的情況自動創(chuàng)建一個FILE結(jié)構(gòu)的變量,并填充其中的信息,使用者不必關(guān)心細節(jié)。
一般都是通過一個FILE的指針來維護這個FILE結(jié)構(gòu)的變量,這樣使用起來更加方便。

下面我們可以創(chuàng)建一個FILE*的指針變量:

FILE* pf;//文件指針變量

定義pf是一個指向FILE類型數(shù)據(jù)的指針變量??梢允筽f指向某個文件的文件信息區(qū)(是一個結(jié)構(gòu)體變量)。通過該文件信息區(qū)中的信息就能夠訪問該文件。也就是說,通過文件指針變量能夠找到與它關(guān)聯(lián)的文件。

2.文件的打開和關(guān)閉

文件在讀寫之前應(yīng)該先打開文件,在使用結(jié)束之后應(yīng)該關(guān)閉文件。

在編寫程序的時候,在打開文件的同時,都會返回一個FILE*的指針變量指向該文件,也相當(dāng)于建立了指針和文件的關(guān)系。

ANSIC 規(guī)定使用fopen函數(shù)來打開文件,fclose來關(guān)閉文件。

要記住的是當(dāng)打開文件后對數(shù)據(jù)進行處理完一定要關(guān)閉文件,否則可能會造成數(shù)據(jù)的丟失。

//打開文件
FILE * fopen ( const char * filename, const char * mode );
//關(guān)閉文件
int fclose ( FILE * stream );

對于文件的寫入和讀取方式,重點掌握以下幾種即可。

文件使用方式含義如果指定文件不存在
“r”(只讀)為了輸入數(shù)據(jù),打開一個已經(jīng)存在的文本文件出錯
“w”(只寫)為了輸出數(shù)據(jù),打開一個文本文件建立一個新的文件
“a”(追加)向文本文件尾添加數(shù)據(jù)建立一個新的文件
“rb”(只讀)為了輸入數(shù)據(jù),打開一個二進制文件出錯
“wb”(只寫)為了輸出數(shù)據(jù),打開一個二進制文件建立一個新的文件

實例代碼:

/* fopen fclose example */
#include <stdio.h>
int main ()
{
  FILE * pFile;
  //打開文件
  pFile = fopen ("myfile.txt","w");//以輸出的形式(寫)打開文件
  //文件操作
  if (pFile!=NULL)
 {
    fputs ("fopen example",pFile);//以字符串的形式寫入
    //關(guān)閉文件
    fclose (pFile);
 }
  return 0; 
}

3.文件的順序讀寫

文件的輸出/寫入就是將數(shù)據(jù)寫入到文件當(dāng)中,而文件的輸入/讀取就是將文件中的內(nèi)容讀取到內(nèi)存當(dāng)中。

以下的對于文件的讀寫方式的函數(shù)均要求掌握

功能函數(shù)名適用于
字符輸入函數(shù)fgetc所有輸入流
字符輸出函數(shù)fputc所有輸出流
文本行輸入函數(shù)fgets所有輸入流
文本行輸出函數(shù)fputs所有輸出流
格式化輸入函數(shù)fscanf所有輸入流
格式化輸出函數(shù)fprintf所有輸出流
二進制輸入fread文件
二進制輸出fwrite文件

四、fseek函數(shù)

根據(jù)文件指針的位置和偏移量來定位文件指針。文件指針顧名思義也是一個指針,它能指向一個字符串中的某個位置。它要接收的參數(shù)有:

第一個參數(shù)是文件指針的名字(流),第二個參數(shù)是文件指針向后偏移數(shù),第三個參數(shù)是fseek函數(shù)中規(guī)定的三個選項之中的其一。

這三項中第一項是SEEK_CUR,即當(dāng)前文件指針的偏移處開始向后偏移。第二項是SEEK_END,即從文件的最末尾處開始向前偏移,當(dāng)然在偏移數(shù)一定要為負數(shù)才能讀取文件中的內(nèi)容。第三項是SEEK_SET,即從文件的最前端處開始向后偏移。舉個例子:

#include <stdio.h>
int main ()
{
  FILE * pFile;
  pFile = fopen ( "example.txt" , "wb" );
  fputs ( "This is an apple." , pFile );
  fseek ( pFile , 9 , SEEK_SET );
  fputs ( " sam" , pFile );
  fclose ( pFile );
  return 0; }

為什么最后在記事本中打印出的結(jié)果是This is a sample.呢?原因是在第一次fputs中是把This is an apple.先放入記事本當(dāng)中,當(dāng)調(diào)用fseek函數(shù)時,從當(dāng)前的文件指針處向后偏移9個字節(jié),文件指針一開始默認指向的是文件的首地址處。因此向后偏移9個字節(jié)后(偏移一個字節(jié)包括空格)指向的是最后一個空格的地址處。而第二次fputs函數(shù)是將“ sam”這個內(nèi)容在上次文件指針指向的地址處開始寫入。因此最后程序運行的結(jié)果如圖:

五、ftell函數(shù)

返回文件指針相對于起始位置的偏移量。

這個函數(shù)比較簡單,輸入的參數(shù)為文件指針流,而返回值的類型為int,即返回的是文件指針所指向的偏移量處。

#include <stdio.h>
int main ()
{
  FILE * pFile;
  long size;
  pFile = fopen ("myfile.txt","rb");
  if (pFile==NULL) perror ("Error opening file");
  else
 {
    fseek (pFile, 0, SEEK_END);   // non-portable
    size=ftell (pFile);
    fclose (pFile);
    printf ("Size of myfile.txt: %ld bytes.\n",size);
 }
  return 0; 
}

因為是從文件內(nèi)容的最末尾處開始相對于起始位置的偏移量。則結(jié)果為17。

代碼運行結(jié)果為:

六、rewind函數(shù)

讓文件指針的位置回到文件的起始位置。

rewind函數(shù)的返回值類型為void型,它所需要的參數(shù)是文件指針流。這個函數(shù)相對來說也比較簡單,我們直接舉例子。

#include <stdio.h>
int main ()
{
  int n;
  FILE * pFile;
  char buffer [27];
  pFile = fopen ("myfile.txt","w+");
  for ( n='A' ; n<='Z' ; n++)
    fputc ( n, pFile);
  rewind (pFile);
  fread (buffer,1,26,pFile);
  fclose (pFile);
  buffer[26]='\0';
  puts (buffer);
  return 0; }

代碼運行結(jié)果:

并且在程序的文件夾中有此內(nèi)容的記事本產(chǎn)生:

七、文本文件和二進制文件

根據(jù)數(shù)據(jù)的組織形式,數(shù)據(jù)文件被稱為文本文件或者二進制文件。

數(shù)據(jù)在內(nèi)存中以二進制的形式存儲,如果不加轉(zhuǎn)換的輸出到外存,就是二進制文件。

如果要求在外存上以ASCII碼的形式存儲,則需要在存儲前轉(zhuǎn)換。以ASCII字符的形式存儲的文件就是文本文件。(如整數(shù)10000,需要以ASCII碼輸出到磁盤上,則在磁盤中的存儲形式就是10000)。

如有整數(shù)10000,如果以ASCII碼的形式輸出到磁盤,則磁盤中占用5個字節(jié)(每個字符一個字節(jié)),而二進制形式輸出,則在磁盤上只占4個字節(jié)(VS2013測試)。

再用整數(shù)10000舉例。如果以二進制的形式輸出到磁盤上,則在磁盤上是以二進制的形式存儲。但是我們到文件底下去看二進制形式的文本時,都是亂碼無法看懂(但機器能夠看懂)。此時我們再將該文本文件移到編譯器(VS2019)中。而編譯器內(nèi)有一個二進制編輯器能夠?qū)⒃搧y碼翻譯為二進制數(shù)顯示出來。詳細步驟如下:

代碼:

#include <stdio.h>
int main()
{
 int a = 10000;
 FILE* pf = fopen("test.txt", "wb");
 fwrite(&a, 4, 1, pf);//二進制的形式寫到文件中
 fclose(pf);
 pf = NULL;
 return 0; }

到文件底下去查看文本:

將該文本移到編譯器中后按照以下圖例操作:

此時我們在編譯器中打開該文本:

是什么原因讓10000用二進制的形式存儲變?yōu)榱?0 27 00 00呢?原因是我們先將10000的二進制序列寫出來,為:00000000 00000000 00100111 00010000,每四位則為一個16進制數(shù)字。則結(jié)果為00 00 27 10,但是我們的編譯器是以小端的形式存儲的。即數(shù)據(jù)的低位存儲到內(nèi)存的低地址中,數(shù)據(jù)的高位存儲到高地址中。則存儲的形式就為:10 27 00 00 。

八、文件讀取結(jié)束的判定

1.feof函數(shù)的錯誤使用

在文件讀取過程中,不能用feof函數(shù)的返回值直接用來判斷文件的是否結(jié)束。

而是應(yīng)用于當(dāng)文件讀取結(jié)束的時候,判斷是讀取失敗結(jié)束,還是遇到文件尾結(jié)束。(feof函數(shù)是判斷結(jié)束過程而不是判斷結(jié)束的結(jié)果)

1.文本文件讀取是否結(jié)束,判斷返回值是否為 EOF(getc)或者NULL(fgets)

例如:

fgetc 判斷是否為 EOF .

fgets 判斷返回值是否為 NULL.

2. 二進制文件的讀取結(jié)束判斷,判斷返回值是否小于實際要讀的個數(shù)。

例如:

fread判斷返回值是否小于實際要讀的個數(shù)。

文件文本中正確使用feof函數(shù)的例子:

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int c; // 注意:int,非char,要求處理EOF
    FILE* fp = fopen("test.txt", "r");
    if(!fp) {
        perror("File opening failed");
        return EXIT_FAILURE;
   }
 //fgetc 當(dāng)讀取失敗的時候或者遇到文件結(jié)束的時候,都會返回EOF
    while ((c = fgetc(fp)) != EOF) // 標準C I/O讀取文件循環(huán)
   { 
       putchar(c);
   }
 //判斷是什么原因結(jié)束的
    if (ferror(fp))
        puts("I/O error when reading");
    else if (feof(fp))
        puts("End of file reached successfully");
    fclose(fp);
}

二進制文件中正確使用feof函數(shù)的例子:

#include <stdio.h>
enum { SIZE = 5 };
int main(void) {
    double a[SIZE] = {1.,2.,3.,4.,5.};
    FILE *fp = fopen("test.bin", "wb"); // 必須用二進制模式
    fwrite(a, sizeof *a, SIZE, fp); // 寫 double 的數(shù)組
    fclose(fp);
    double b[SIZE];
    fp = fopen("test.bin","rb");
    size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 讀 double 的數(shù)組
    if(ret_code == SIZE) {
        puts("Array read successfully, contents: ");
        for(int n = 0; n < SIZE; ++n) printf("%f ", b[n]);
        putchar('\n');
   } else { // error handling
       if (feof(fp))
          printf("Error reading test.bin: unexpected end of file\n");
       else if (ferror(fp)) {
           perror("Error reading test.bin");
       }
   }
    fclose(fp);
}

九、文件緩沖區(qū)

說到文件緩沖區(qū),我們就自然而然想到輸入緩沖區(qū),即當(dāng)一個字符一個字符從鍵盤上輸入時,并不是直接輸入到磁盤內(nèi),而是先放到輸入緩沖區(qū),而當(dāng)輸入緩沖區(qū)內(nèi)的字符放滿后,文件緩沖區(qū)才向磁盤內(nèi)輸入字符。

文件緩沖區(qū)也是一樣的道理。從內(nèi)存向磁盤輸出數(shù)據(jù)會先送到內(nèi)存中的緩沖區(qū),裝滿緩沖區(qū)后才一起送到磁盤上。如果從磁盤向計算機讀入數(shù)據(jù),則從磁盤文件中讀取數(shù)據(jù)輸入到內(nèi)存緩沖區(qū)(充滿緩沖區(qū)),然后再從緩沖區(qū)逐個地將數(shù)據(jù)送到程序數(shù)據(jù)區(qū)(程序變量等)。緩沖區(qū)的大小根據(jù)C編譯系統(tǒng)決定的。

測試代碼:

#include <stdio.h>
#include <windows.h>
//VS2013 WIN10環(huán)境測試
int main()
{
 FILE*pf = fopen("test.txt", "w");
 fputs("abcdef", pf);//先將代碼放在輸出緩沖區(qū)
 printf("睡眠10秒-已經(jīng)寫數(shù)據(jù)了,打開test.txt文件,發(fā)現(xiàn)文件沒有內(nèi)容\n");
 Sleep(10000);
 printf("刷新緩沖區(qū)\n");
 fflush(pf);//刷新緩沖區(qū)時,才將輸出緩沖區(qū)的數(shù)據(jù)寫到文件(磁盤)
 //注:fflush 在高版本的VS上不能使用了
 printf("再睡眠10秒-此時,再次打開test.txt文件,文件有內(nèi)容了\n");
 Sleep(10000);
 fclose(pf);
 //注:fclose在關(guān)閉文件的時候,也會刷新緩沖區(qū)
 pf = NULL;
 return 0; }

我們可以測試一下這個代碼,在程序第一個到fgets函數(shù)處時,立刻去打開test.txt文本文件,我們會發(fā)現(xiàn)里面沒有內(nèi)容,而我們用刷新文件緩沖區(qū)的fflush函數(shù)時再次打開test.txt文本文件時,會發(fā)現(xiàn)里面已經(jīng)有輸入的內(nèi)容。則能夠證實的確有文件緩沖區(qū)的存在。

因為有緩沖區(qū)的存在,C語言在操作文件的時候,需要做刷新緩沖區(qū)或者在文件操作結(jié)束的時候關(guān)閉文件。如果不做,可能導(dǎo)致讀寫文件的問題。

總結(jié)

到此這篇關(guān)于C語言文件操作的文章就介紹到這了,更多相關(guān)C語言文件操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c語言字符串函數(shù)strstr,strtok,strerror的使用和實現(xiàn)

    c語言字符串函數(shù)strstr,strtok,strerror的使用和實現(xiàn)

    C語言中的字符串處理函數(shù)如strtok、strstr和strerror對于字符串的處理有著重要的作用,strtok函數(shù)用于分割字符串,它通過sep參數(shù)指定的分隔符來分割str參數(shù)指定的字符串,并返回分割后的每個子字符串
    2024-10-10
  • c語言沒有try catch的替代方案

    c語言沒有try catch的替代方案

    這篇文章主要介紹了c語言沒有try catch的替代方案,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • C語言合并兩個帶頭節(jié)點升序排列鏈表

    C語言合并兩個帶頭節(jié)點升序排列鏈表

    這篇文章主要為大家詳細介紹了C語言合并兩個帶頭節(jié)點升序排列鏈表的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • C語言實現(xiàn)abs和fabs絕對值

    C語言實現(xiàn)abs和fabs絕對值

    這篇文章主要介紹了C語言實現(xiàn)abs和fabs絕對值,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • c語言中static和extern的用法詳細解析

    c語言中static和extern的用法詳細解析

    以下是對c語言中static和extern的用法進行了詳細的分析介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-09-09
  • C語言實現(xiàn)的猴子偷桃之類算法

    C語言實現(xiàn)的猴子偷桃之類算法

    本文給大家分享的是前些日子去面試的時候的試題,哎,真是沒想到會出這么個題,好多年沒碰過C了。。。。分享給大家,小伙伴們過來參觀下吧。
    2015-03-03
  • Visual Studio 2019安裝、測試創(chuàng)建c語言項目(圖文教程)

    Visual Studio 2019安裝、測試創(chuàng)建c語言項目(圖文教程)

    這篇文章主要介紹了Visual Studio 2019安裝、測試創(chuàng)建c語言項目,Visual Studio 2019是完全免費的,而且安裝比較簡單,現(xiàn)在把安裝步驟分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2020-03-03
  • C語言靜態(tài)鏈表和動態(tài)鏈表

    C語言靜態(tài)鏈表和動態(tài)鏈表

    靜態(tài)鏈表和動態(tài)鏈表是線性表鏈式存儲結(jié)構(gòu)的兩種不同的表示方式。靜態(tài)鏈表的初始長度一般是固定的,在做插入和刪除操作時不需要移動元素,僅需修改指針。動態(tài)鏈表是相對于靜態(tài)鏈表而言的,一般地,在描述線性表的鏈式存儲結(jié)構(gòu)時如果沒有特別說明即默認描述的是動態(tài)鏈表。
    2016-05-05
  • C語言中數(shù)組的使用詳解

    C語言中數(shù)組的使用詳解

    這篇文章主要為大家介紹了C語言中數(shù)組的使用,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • C語言編程技巧 關(guān)于const和#define的區(qū)別心得

    C語言編程技巧 關(guān)于const和#define的區(qū)別心得

    盡量用const和inline而不用#define 這個條款最好稱為:“盡量用編譯器而不用預(yù)處理”,因為#define經(jīng)常被認為好象不是語言本身的一部分。這是問題之一。再看下面的語句:
    2013-02-02

最新評論

滦平县| 合江县| 蛟河市| 始兴县| 浑源县| 辽源市| 和顺县| 阳城县| 承德市| 吉木乃县| 拉萨市| 杭州市| 大洼县| 乌恰县| 公主岭市| 竹溪县| 卢龙县| 铁岭县| 博客| 巧家县| 天镇县| 大理市| 绵阳市| 青冈县| 崇礼县| 安阳市| 浦江县| 吐鲁番市| 天全县| 阳江市| 五寨县| 临沭县| 榆树市| 安西县| 永州市| 北流市| 桂东县| 珲春市| 福建省| 老河口市| 普宁市|