C語言基礎(20)-文件操作(fopen,getc,fclose)


 

一.文件操作

讀文件的順序:

1.先打開文件

2.讀寫文件

3.關閉文件

1.1 fopen

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

函數說明:
1.path就是指定打開文件的路徑,可以是相對路徑,也可以絕對路徑。mode代表打開文件的方式 2.fopen打開成功,返回FILE的有效地址,失敗返回NULL. 3.fopen返回的指針是不能自己計算的,一定是要給C語言文件操作的庫函數操作的

以只讀方式打開文件,該文件必須存在,文件必須是可讀的。

 
         

r+ 以可讀寫方式打開文件,該文件必須存在。

 
         

rb+ 讀寫打開一個二進制文件,允許讀寫數據,文件必須存在。

 
         

rw+ 讀寫打開一個文本文件,允許讀和寫。

 
         

打開只寫文件,若文件存在則文件長度清為0,即該文件內容會消失。若文件不存在則建立該文件。

 
         

w+ 打開可讀寫文件,若文件存在則文件長度清為零,即該文件內容會消失。若文件不存在則建立該文件。

 
         

以附加的方式打開只寫文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾,即文件原先的內容會被保留。(EOF符保留)

 
         

a+ 以附加方式打開可讀寫的文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾后,即文件原先的內容會被保留。 (原來的EOF符不保留)

 

1.2 getc

int getc( FILE *stream ); 
函數說明:
1.getc的功能是一個字節一個字節的讀取文件內容
2.stream代表返回的FILE有效地址

1.3 fclose

int fclose( FILE *stream );
函數說明:
函數fclose()關閉給出的文件流, 釋放已關聯到流的所有緩沖區. fclose()執行成功時返回0,否則返回EOF.

示例代碼:

#include <stdlib.h>
#include <stdio.h>

#pragma warning(disable:4996)

void fopenUseDemo(void);


int main()
{
    
    fopenUseDemo();
    system("pause");
    return 0;

}



void fopenUseDemo(void)
{
    // p 這個指針一般不用來計算,主要的用處是給C語言庫函數作為參數
    // 1.打開文件
    FILE *p = fopen("E:\\CrackCaptcha.log","r");
    if (p == NULL) {
        printf("文件打開失敗\n");
    }else {
        //printf("文件打開成功\n");
        //char c = getc(p);
        //printf("%c\n",c); // 輸出2
        //char d = getc(p); // 第二次調用getc的時候,getc會自動從第二個BYTE開始讀取文件的內容,這個是不需要我們通過代碼干預的。
        //printf("%c\n", d);// 輸出0
        
        // 2.讀取文件內容
        char c = 0;
        while (c != EOF) // 只要不是文件結尾,那么就一直循環
        {
            c = getc(p);
            printf("%c",c);
        }

        // 3.關閉文件
        fclose(p); // p代表fopen成功返回的值
    }

}

輸出結果:

1.4 putc

int fputc( int ch, FILE *stream );
函數說明:
1.第一個參數是要寫入的char 2.第二個參數是fopen返回的指針

示例代碼:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void fopenUseDemo1(void);
void fopenUseDemo2(void);

// int fputc( int ch, FILE *stream );
// 第一個參數是要寫入的char
// 第二個參數是fopen返回的指針

void fopenUseDemo1(void)
{
    FILE *p = fopen("E:\\xp.chen.txt","w");
    if (p)
    {
        printf("執行成功\n");
        char a[100] = "hello world";
        int len = strlen(a);
        for (int i = 0; i < len; i++)
            putc(a[i],p);
        fclose(p);
    }

}


// 實現簡單的文件拷貝
void fopenUseDemo2(void)
{
    FILE *p1 = fopen("E:\\xp.chen.txt","r");
    FILE *p2 = fopen("E:\\naruto.txt","w");
    if (p1&&p2)
    {
        // 讀取p1,將讀取到的內容寫入p2,就實現了文件的拷貝
        char c = 0;
        while (1)
        {
            char c = getc(p1); // 從p1中讀一個字節
            if (c == EOF)
                break;
            putc(c,p2); // 將p1中讀到的字節寫到p2
        }
        fclose(p1);
        fclose(p2);
    }

    
}

1.5 fgets

char *fgets( char *str, int num, FILE *stream );
函數說明: 1.第一個參數代表待存儲的字符串,第二個參數代表待存儲的字符串的長度,第三個參數代表打開的文件路徑

示例Demo:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>


void fgetsUseDemo(void);

void fgetsUseDemo(void)
{
    
    FILE *p = fopen("E:\\naruto.txt","r");
    if (p)
    {
        //char a[100] = {0};
        //fgets(a, sizeof(a), p);//從p中讀一行,包括行尾的回車
        //printf("%s\n",a);

        // 示例1:循環讀取文件內容
        //while (1)
        //{
        //    char a[100] = {0};
        //    fgets(a,sizeof(a),p); // 從p中讀一行,包括行尾的回車
        //    if (feof(p)) // 如果p已經到了文件最后,feof返回true
        //        break;
        //    printf("%s",a);
        //}

        char a[100] = {0};
        fgets(a,sizeof(a),p);
        printf("%s",a);

        // 示例2:循環讀取所有文件內容
        while (!feof(p))
        {
            char a[100] = {0};
            fgets(a,sizeof(a),p);
            printf("%s",a);
        }

        fclose(p);
    }

}
int feof( FILE *stream );
注意:
1.如果文件已經到達文件結尾,feof()函數返回true 2.傳入的參數是fopen返回的文件指針

1.6 fputs

int fputs( const char *str, FILE *stream );
函數說明: 1. 第一個參數代表需要寫入的內容,第二個參數代表將要寫入的文件
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void fputsUseDmeo(void);

void fputsUseDmeo(void)
{
    
    FILE *p = fopen("E:\\xp.chen.txt","w");
    if (p)
    {
        char a[100] = "仙法!超大玉螺旋手里劍";
        fputs(a,p);
    }


}

 

1.7 fprintf()

 int fprintf( FILE *stream, const char *format, ... );
 函數說明
 1.用法和printf一樣,只是多了第一個參數,該參數代表打開的文件指針
// int fprintf( FILE *stream, const char *format, ... );
void fprintfUseDemo(void)
{
    FILE *p = fopen("E:\\temp.txt","w");
    char a[100] = "hello";
    fprintf(p,"%s",a); // 用法和printf一樣,只是多了第一個參數,參數是打開的文件指針

    int a1 = 4;
    int a2 = 5;

    /*sprintf(a,"%d%d",a1,a2);
    fputs(a,p);*/

    fprintf(p,"%d,%d",a1,a2);
    fclose(p);
    
}

1.8 fscanf

int fscanf( FILE *stream, const char *format, ... );
函數說明: 1.第一個參數代表打開的文件指針
2.第二個參數代表匹配的文本
3.第三個參數代表需要賦值的變量指針。

示例代碼:

假設E盤下有有一文本文件為xp.chen.txt,內容為:

則可通過fscanf來計算以上兩個表達式的和

void fscanfUseDemo1(void)
{

    FILE *p = fopen("E:\\xp.chen.txt","r");
    int a1, a2;
    fscanf(p,"%d+%d",&a1,&a2);
    //printf("a1=%d, a2=%d\n",a1,a2);
    printf("%d\n",a1+a2); // 計算當前兩個數的和
    fscanf(p, "%d+%d", &a1, &a2);
    //printf("a1=%d, a2=%d\n", a1, a2);
    printf("%d\n",a1+a2);
    fclose(p);

}

1.9 stat()

int  stat(const char * _Filename, struct stat * _Stat)
函數說明 1.該函數用於獲取當前文件的狀態
2.第一個參數代表當前文件的完整路徑,第二個參數代表包含當前文件狀態的結構體指針。

示例代碼:

void statFuntionUseDemio(void)
{

    struct stat fileStates = {0};
    struct stat *p = &fileStates;
    const char *filePath = "E:\\xp.chen.txt";

    stat(filePath,p);

    _off_t fileSize = fileStates.st_size; // _off_t其實就是long類型
    printf("當前這個文件的大小為:%ld\n",fileSize);

}

輸出結果:

 

同時通過該函數可以獲取文件的其它狀態信息(文件大小,最后一次修改時間,文件屬性...)

1.10 fwrite()

int fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
函數說明 1.該函數用於寫二進制數據到文件
2.第一個參數代表待寫數據的內存地址
3.第二個參數代表寫多少個單位
4.第三個參數代表每個單位的大小
5.第四個參數是fopen返回的文件指針。

示例代碼:

void fwriteUseDemo1(void)
{
    int array[10] = {1,2,3,4,5,6,7,8,9,10};
    FILE *file = fopen("E:\\xp.chen.data","wb");
    fwrite(array,1,sizeof(array),file);
    fclose(file);

}

1.11 fread()

int fread( void *buffer, size_t size, size_t num, FILE *stream );
函數說明 該函數用於讀取二進制文件
1.第一個參數代表將要讀入的buffer
2.第二個參數代表讀多少個單位
3.第三個參數代表每個單位的大小
4.第四個參數代表待讀取文件的路徑。

示例Demo1:

// 讀取二進制文件內容
void freadUseDemo(void)
{

    FILE *p = fopen("E:\\xp.chen.data","rb");
    while (!feof(p))
    {
        int a;
        int rec = fread(&a,sizeof(a),1,p); // 一個單位是1個字節,fread的返回值代表讀取了多少個單位,而不是字節
        //printf("%d\n",a);
        printf("rec=%d,a=%d\n",rec,a);
    }
    
    fclose(p);

}

輸出結果:

示例Demo2:

void freadUseDemo1(void)
{
    FILE *p = fopen("E:\\xp.chen.data","rb");
    while (1)
    {
        int a;
        if (fread(&a, 1, sizeof(a), p) == 0) // 當讀取的單位數為0的時候結束讀取
            break;
        printf("a = %d\n",a);
    }

}

輸出結果:

示例Demo3:

// 實現文件拷貝
void freadUseDemo2(void)
{
    
    FILE *p1 = fopen("E:\\loginsdk.jar","rb");
    FILE *p2 = fopen("E:\\xxx.jar","wb");
    if (p1 == NULL)
        return;
    if (p2 == NULL)
        return;
    while (1)
    {
        int a;
        int rc = fread(&a,1,sizeof(a),p1); // rc可以認為是從p1中讀取到字節數
        if (rc == 0)
            break;
        fwrite(&a, 1, rc, p2);
        
    }
    fclose(p1);
    fclose(p2);

}

1.12 fseek()和ftell()

int fseek( FILE *stream, long offset, int origin );
函數說明 1.第一個參數代表fopen打開的文件路徑
2.第二個參數代表位移
3.第三個參數代表從什么地方開始

ftell()

long ftell( FILE *stream );
函數說明 1.ftell的功能可以知道指針當前在文件的什么地方

示例代碼:

//  int fseek( FILE *stream, long offset, int origin );
// 第一個參數代表fopen返回的文件指針
// 第二個參數代表位移
// 第三個參數代表從什么開始
void fseekUseDemo(void)
{

    /*char a[10] = {1,2,3,4,5,6,7,8,9,10};
    FILE *p = fopen("E:\\xp.chen.dat","wb");
    fwrite(&a,1,sizeof(a),p);
    fclose(p);*/


    char a[2];
    FILE *p = fopen("E:\\xp.chen.dat", "rb");
    // 第一次打開文件的時候,指針位於文件的開始位置
    //fseek(p,0,SEEK_SET);//  代表回到起始位置
    // fseek(p,-4,SEEK_END); 代表從最后往前移動4個字節
    fseek(p,0,SEEK_END); // 回到最后位置
    fseek(p,2,SEEK_SET); // SEEK_SET代表文件開始,這句話的意思就是從文件開始向后移動兩個字節
    fread(&a,1,sizeof(a),p); // 所有的C語言文件讀寫庫函數都會自動維護fopen返回的文件指針
    printf("%d,%d\n",a[0],a[1]);

    printf("ftell = %ld\n",ftell(p)); // ftell的功能可以知道指針當前在文件的什么地方

    // 通過下列方式可以計算出文件大小
    // fseek(p,0,SEEK_END); // 先使用SEEK_END將指針移動到文件最后
    // ftell(p);//然后使用ftell獲得最后的偏移字節數,也就是文件的大小
    fclose(p);

}

運行結果:

1.13 fflush()

int fflush( FILE *stream );
函數說明 1.fflush函數可以將緩沖區中任何未寫入的數據立刻寫入文件中

示例代碼:

// 由於fflush是實時將緩沖區的內容寫入到磁盤,所有不要大量的使用,但
// 如果是特別敏感的數據,可以通過fflush寫入磁盤,防止由於電腦各種故障,
// 內存數據丟失
void fflushFunctionUseDemo(void)
{
    FILE *p = fopen("E:\\xp.chen.txt","w");
    while (1)
    {
        char a[100] = {0};
        scanf("%s",a);
        if (strcmp(a, "exit") == 0)
            break;
        fputs(a,p);
        putc('\n',p);
        fflush(p); // fflush函數可以將緩沖區中任何未寫入的數據立刻寫入文件中
    }
    fclose(p);
}

運行結果:

1.14 remove()和rename()

void remove( const TYPE &val );
函數說明: 刪除文件,參數為文件路徑

rename()

int rename( const char *oldfname, const char *newfname );
函數說明: 函數rename()更改文件oldfname的名稱為newfname. rename()成功時返回0,錯誤時返回非零. 

示例代碼:

void removeFunctionUseDemo(void)
{
    //remove("E:\\xp.chen.txt"); // 刪除指定文件
    rename("E:\\xxx.jar","E:\\nimabi.jar");
}

 

二.二進制和文本模式的區別

1.windows系統中,文本模式下,文件以"\r\n"代表換行。若以文本模式打開文件,並用fputs等函數寫入換行符"\n"時,函數會自動在"\n"前面加上"\r"。即實際寫入文件的是"\r\n" 

2.在類Unix/Linux系統中文本模式下,文件以"\n"代表換行。所以Linux系統中在文本模式和二進制模式下並無區別。

3.在windows下,讀寫文本文件的時候,是不寫b的,但讀寫二進制文件的時候一定要寫b,Linux,b是忽略的。

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM