C語言 文件操作


C語言 文件操作

文件概述

一、磁盤文件和設備文件

1、磁盤文件

指一組相關數據的有序集合,通常存儲在外部介質(如磁盤)上,使用時才調入內存。

2、設備文件

在操作系統中把每一個與主機相連的輸入、輸出設備看作是一個文件,把它們的輸入、輸出等同於對磁盤文件的讀和寫。

二、磁盤文件的分類

計算機的存儲在物理上是二進制的,所以物理上所有的磁盤文件本質上都是一樣的:以字節為單位進行順序存儲。

 從用戶或者操作系統使用的角度(邏輯上)把文件分為:

  • 文本文件:基於字符編碼的文件
  • 二進制文件:基於值編碼的文件

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

1、文本文件

  • 基於字符編碼,常見編碼有ASCII、UNICODE等
  • 一般可以使用文本編輯器直接打開

數5678的以ASCII存儲形式(ASCII碼)為:

00110101 00110110 00110111 00111000

2、二進制文件

  • 基於值編碼,自己根據具體應用,指定某個值是什么意思
  • 把內存中的數據按其在內存中的存儲形式原樣輸出到磁盤上

 數5678的存儲形式(二進制碼)為:

00010110 00101110

文件打開和關閉

一、文件指針

在C語言中用一個指針變量指向一個文件,這個指針稱為文件指針

typedef struct
{
       short           level;       //緩沖區"滿"或者"空"的程度
       unsigned        flags;       //文件狀態標志
       char            fd;          //文件描述符
       unsigned char   hold;        //如無緩沖區不讀取字符
       short           bsize;       //緩沖區的大小
       unsigned char   *buffer;     //數據緩沖區的位置
       unsigned        ar;          //指針,當前的指向
       unsigned        istemp;      //臨時文件,指示器
       short           token;       //用於有效性的檢查
}FILE;

  FILE是系統使用typedef定義出來的有關文件信息的一種結構體類型,結構中含有文件名、文件狀態和文件當前位置等信息。

  聲明FILE結構體類型的信息包含在頭文件“stdio.h”中,一般設置一個指向FILE類型變量的指針變量,然后通過它來引用這些FILE類型變量。通過文件指針就可對它所指的文件進行各種操作。

C語言中有三個特殊的文件指針由系統默認打開,用戶無需定義即可直接使用:

  • stdin: 標准輸入,默認為當前終端(鍵盤),我們使用的scanf、getchar函數默認從此終端獲得數據。
  • stdout:標准輸出,默認為當前終端(屏幕),我們使用的printf、puts函數默認輸出信息到此終端。
  • stderr:標准出錯,默認為當前終端(屏幕),我們使用的perror函數默認輸出信息到此終端。

二、文件打開

1、說明

任何文件使用之前必須打開:

#include <stdio.h>
FILE * fopen(const char * filename, const char * mode);

功能:打開文件
參數:

  • filename:需要打開的文件名,根據需要加上路徑
  • mode:打開文件的模式設置

返回值:

  • 成功:文件指針
  • 失敗:NULL

2、第一個參數的幾種形式

FILE *fp_passwd = NULL;
 
//相對路徑:
//打開當前目錄passdw文件:源文件(源程序)所在目錄
FILE *fp_passwd = fopen("passwd.txt", "r");
      
//打開當前目錄(test)下passwd.txt文件
fp_passwd = fopen(". / test / passwd.txt", "r");
      
//打開當前目錄上一級目錄(相對當前目錄)passwd.txt文件
fp_passwd = fopen(".. / passwd.txt", "r");
             
//絕對路徑:
//打開C盤test目錄下一個叫passwd.txt文件
fp_passwd = fopen("c://test//passwd.txt","r");

3、第二個參數的幾種形式(打開文件的方式)

注意事項:

  • b是二進制模式的意思,b只是在Windows有效,在Linux用r和rb的結果是一樣的
  • Unix和Linux下所有的文本文件行都是\n結尾,而Windows所有的文本文件行都是\r\n結尾
  • 在Windows平台下,以“文本”方式打開文件,不加b:
  • 當讀取文件的時候,系統會將所有的 "\r\n" 轉換成 "\n"
  • 當寫入文件的時候,系統會將 "\n" 轉換成 "\r\n" 寫入
  • 以"二進制"方式打開文件,則讀\寫都不會進行這樣的轉換
  • 在Unix/Linux平台下,“文本”與“二進制”模式沒有區別,"\r\n" 作為兩個字符原樣輸入輸出

打開模式

含義

r或rb

以只讀方式打開一個文本文件(不創建文件,若文件不存在則報錯)

w或wb

以寫方式打開文件(如果文件存在則清空文件,文件不存在則創建一個文件)

a或ab

以追加方式打開文件,在末尾添加內容,若文件不存在則創建文件

r+或rb+

以可讀、可寫的方式打開文件(不創建新文件)

r+或rb+

以可讀、可寫的方式打開文件(不創建新文件)

w+或wb+

以可讀、可寫的方式打開文件(如果文件存在則清空文件,文件不存在則創建一個文件)

a+或ab+

以添加方式打開文件,打開文件並在末尾更改文件,若文件不存在則創建文件

4、案例

#include <stdio.h>

int main(void)
{
       FILE *fp = NULL;
 
       // "\\"這樣的路徑形式,只能在windows使用
       // "/"這樣的路徑形式,windows和linux平台下都可用,建議使用這種
       // 路徑可以是相對路徑,也可是絕對路徑
       fp = fopen("../test", "w");
       //fp = fopen("..\\test", "w");
 
       if (fp == NULL) //返回空,說明打開失敗
       {
              //perror()是標准出錯打印函數,能打印調用庫函數出錯原因
              perror("open");
              return -1;
       }
 
       return 0;
}
文件打開 使用案例

三、文件關閉

1、說明

任何文件在使用后應該關閉:

  • 打開的文件會占用內存資源,如果總是打開不關閉,會消耗很多內存
  • 一個進程同時打開的文件數是有限制的,超過最大同時打開文件數,再次調用fopen打開文件會失敗
  • 如果沒有明確的調用fclose關閉打開的文件,那么程序在退出的時候,操作系統會統一關閉。
#include <stdio.h>
int fclose(FILE * stream);

功能:關閉先前fopen()打開的文件。此動作讓緩沖區的數據寫入文件中,並釋放系統所提供的文件資源。
參數:

  • stream:文件指針

返回值:

  • 成功:0
  • 失敗:-1

2、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 定義文件指針
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
    
    // 判斷文件是否打開成功
    // 1、找不到文件
    // 2、文件權限(讀、寫、執行)
    // 3、程序打開文件超出上限 65535
    if (fp == NULL)
    {
        printf("打開文件失敗\n");
        return -1;
    }
    
    printf("文件打開成功:%p\n",fp);
    
    // 關閉文件指針
    fclose(fp);

    return 0;
}
文件關閉 使用案例

文件字符讀寫

一、寫文件

1、說明

#include <stdio.h>
int fputc(int ch, FILE * stream);

功能:將ch轉換為unsigned char后寫入stream指定的文件中
參數:

  • ch:需要寫入文件的字符
  • stream:文件指針

返回值:

  • 成功:成功寫入文件的字符
  • 失敗:返回-1

2、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 以寫的方式打開文件、如果文件不存在則創建一個新文件、如果文件存在則清空內容
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w");
    
    if (!fp)
    {
        printf("打開文件失敗\n");
        return -1;
    }
    
    // 創建字符
    // char ch = 'a';

    // 字符寫入
    // 約束:if(value==-1)
    // fputc(ch, fp);
    
    // 通過鍵盤輸入方式存字符
    char ch;
    while (1)
    {
        scanf("%c", &ch);
        // 輸入@關閉文件
        if (ch == '@')
        {
            break;
        }
        fputc(ch, fp);
    }


    // 關閉文件
    fclose(fp);

    return 0;
}
fputc 使用案例

二、文件結尾

1、概述

  在C語言中,EOF表示文件結束符(end of file)。在while循環中以EOF作為文件結束標志,這種以EOF作為文件結束標志的文件,必須是文本文件。在文本文件中,數據都是以字符的ASCII代碼值的形式存放。我們知道,ASCII代碼值的范圍是0~127,不可能出現-1,因此可以用EOF作為文件結束標志。

#define EOF     (-1)

  當把數據以二進制形式存放到文件中時,就會有-1值的出現,因此不能采用EOF作為二進制文件的結束標志。為解決這一個問題,ANSI C提供一個feof函數,用來判斷文件是否結束。feof函數既可用以判斷二進制文件又可用以判斷文本文件。

2、說明

#include <stdio.h>
int feof(FILE * stream);

功能:檢測是否讀取到了文件結尾。判斷的是最后一次“讀操作的內容”,不是當前位置內容(上一個內容)。
參數:

  • stream:文件指針

返回值:

  • 非0值:已經到文件結尾
  • 0:沒有到文件結尾

3、案例

三、讀文件

1、說明

#include <stdio.h>
int fgetc(FILE * stream);

功能:從stream指定的文件中讀取一個字符
參數:

  • stream:文件指針

返回值:

  • 成功:返回讀取到的字符
  • 失敗:-1

2、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
    
    if (!fp)
    {
        printf("打開文件失敗\n");
        return -1;
    }
    
    // 定義字符
    char ch;

    // 文件字符讀取
    // 文件默認結尾為 -1
    // ch = fgetc(fp);

    // 不能修改文件指針
    // 文件在讀取時光標流會自動向下移動
    // fp++;

    // 循環打印
    while ((ch = fgetc(fp)) != EOF)
    {
        printf("%c", ch);
    }

    // 關閉文件
    fclose(fp);

    return 0;
}
fgetc 使用案例

四、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    FILE* fp1 = fopen("C:/Users/Administrator/Desktop/解密.txt", "r");
    FILE* fp2 = fopen("C:/Users/Administrator/Desktop/加密.txt", "w");
 if (!fp1 || !fp2)return -1;
    char ch;
    while ((ch = fgetc(fp1)) != EOF)
    {
        // 加密
        ch++;
        fputc(ch, fp2);
    }

    fclose(fp1);
    fclose(fp2);

    return 0;
}
字符讀寫 使用案例:加密
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    FILE* fp1 = fopen("C:/Users/Administrator/Desktop/加密.txt", "r");
    FILE* fp2 = fopen("C:/Users/Administrator/Desktop/解密文件.txt", "w");
    if (!fp1 || !fp2)return -1;
    char ch;
    while ((ch = fgetc(fp1)) != EOF)
    {
        // 解密
        ch--;
        fputc(ch, fp2);
    }

    fclose(fp1);
    fclose(fp2);

    return 0;
}
字符讀寫 使用案例:解密

文件行讀寫

一、寫文件

1、說明

#include <stdio.h>
int fputs(const char * str, FILE * stream);

功能:將str所指定的字符串寫入到stream指定的文件中,字符串結束符 '\0' 不寫入文件。
參數:

  • str:字符串
  • stream:文件指針

返回值:

  • 成功:0
  • 失敗:-1

2、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 打開文件
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w");
    // 判斷
    if (!fp)return -1;

    // 創建字符串
    // "你想怎\0么滴吧" 遇到\0則停止
    // char ch[] = "你想怎么滴吧";
    //fputs(ch, fp);

    // 通過鍵盤輸入獲取字符串
    char* p = (char*)malloc(sizeof(char) * 1024);
    while (1)
    {
        memset(p, 0, 1024);
        
        // 問題:scanf("%s", p);無法接收回車空格
        // 方式一、fgets() 可接收空格
        // 方式二、scanf("%[^\n]", p); 避免吞噬空格回車
        scanf("%[^\n]", p);
        // 吞噬回車\n
        getchar();

        // 停止輸入命令:comm=exit
        if (!strcmp(p, "comm=exit",9))break;

        // 追加換行符
        strcat(p, "\n");

        // 寫入字符串
        fputs(p, fp);
    }

    free(p);
    fclose(fp);

    return 0;
}
fputs 使用案例

二、讀文件

1、說明

#include <stdio.h>
char * fgets(char * str, int size, FILE * stream);

功能:從stream指定的文件內讀入字符,保存到str所指定的內存空間,直到出現換行字符、讀到文件結尾或是已讀了size - 1個字符為止,最后會自動加上字符 '\0' 作為字符串結束。
參數:

  • str:字符串
  • size:指定最大讀取字符串的長度(size - 1)
  • stream:文件指針

返回值:

  • 成功:成功讀取的字符串
  • 讀到文件尾或出錯: NULL

2、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 打開文件
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
    // 判斷
    if (!fp)return -1;

    // 開辟堆空間
    char* p = (char*)malloc(sizeof(char) * 1024);
    
    // 初始化內存空間 
    // memset(p, 0, 5);
    // 通過堆開放內存,打印文件中100個字節
    // 根據光標位置繼續向下讀取字符串
    // fgets(p, 5, fp);
    // printf("%s", p);
    
    // 打印
    // feof(文件指針):判斷文件是否到結尾 可以判斷文本文件也可以判斷二進制文件
    // 如果到文件結尾返回值為 非0的值
    // 如果沒到文件結尾返回值為 0的值
    while (!feof(fp))
    {
        memset(p, 0, 100);
        fgets(p, 100, fp);
        printf("%s", p);
    }

    free(p);
    fclose(fp);

    return 0;
}
fgets 使用案例

三、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

enum opt
{
    add,sub,mlt,dive
};

int main(void)
{
    
    srand((size_t)time(NULL));
    
    // 打開文件
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w");
    // 判斷
    if (!fp)return -1;

    int a, b;
    char c; // + - * /
    char * p = (char*)malloc(sizeof(char) * 20);

    for (int i = 0; i < 100; i++)
    {
        a = rand() % 10 + 1;
        b = rand() % 10 + 1;

        switch (rand() % 4)
        {
        case add:c = '+';break;
        case sub:c = '-';break;
        case mlt:c = '*';break;
        case dive:c = '/';break;
        }

        memset(p, 0,20);
        sprintf(p, "%d%c%d=\n", a, c, b);
        fputs(p, fp);//fgets(p,size,fp)

    }

    free(p);
    fclose(fp);
    p = NULL;
    fp = NULL;

    return 0;
}
文件行讀寫 使用案例:四則運算(打印運算表達式)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    
    srand((size_t)time(NULL));
    
    // 打開文件
    FILE* fp1 = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
    FILE* fp2 = fopen("C:/Users/Administrator/Desktop/xsk2.txt", "w");
    // 判斷
    if (!fp1 || !fp2)return -1;

    // 判斷文件結尾
    // !feof(fp);
    // EOF -1

    int a, b, sum;
    char c;
    char * p = (char*)malloc(sizeof(char) * 20);

    for (int i = 0; i < 100; i++)
    {
        memset(p, 0, 20);
        // 打印1行內容
        fgets(p, 20, fp1);

        sscanf(p, "%d%c%d=\n", &a, &c, &b);

        switch (c)
        {
        case '+':sum = a + b; break;
        case '-':sum = a - b; break;
        case '*':sum = a * b; break;
        case '/':sum = a / b; break;
        }

        memset(p, 0, 20);
        sprintf(p, "%d%c%d=%d\n", a, c, b, sum);
        fputs(p, fp2);
    }

    free(p);
    fclose(fp1);
    fclose(fp2);

    return 0;
}
文件行讀寫 使用案例:四則運算(打印運算表達式結果)

文件格式化

一、寫文件

1、說明

#include <stdio.h>
int fprintf(FILE * stream, const char * format, ...);

功能:根據參數format字符串來轉換並格式化數據,然后將結果輸出到stream指定的文件中,指定出現字符串結束符 '\0' 為止。
參數:

  • stream:已經打開的文件
  • format:字符串格式,用法和printf()一樣

返回值:

  • 成功:實際寫入文件的字符個數
  • 失敗:-1

2、案例

二、讀文件

1、說明

#include <stdio.h>
int fscanf(FILE * stream, const char * format, ...);

功能:從stream指定的文件讀取字符串,並根據參數format字符串來轉換並格式化數據。
參數:

  • stream:已經打開的文件
  • format:字符串格式,用法和scanf()一樣

返回值:

  • 成功:參數數目,成功轉換的值的個數
  • 失敗: - 1

2、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    
    // 打開文件
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
    // 判斷
    if (!fp)return -1;

    char * p = (char*)malloc(sizeof(char) * 100);
    
    // 直接格式化取出字符串
    // 遇到空格與回車就結束
    // fscanf(fp, "%s", p);
    // printf("%s", p);


    int a, b, c;

    // 1+2=3
    // 處理表達式
    fscanf(fp, "%d+%d=%d", &a,&b,&c);

    printf("%d\n", a);
    printf("%d\n", b);
    printf("%d\n", c);

    free(p);
    fclose(fp);

    return 0;
}
fscanf 使用案例

三、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    srand((size_t)time(NULL));
    // 打開文件
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk1.txt", "w");
    // 判斷
    if (!fp)return -1;

    int a, b;
    char c;

    for (int i = 0; i < 100; i++)
    {
        a = rand() % 10 + 1;
        b = rand() % 10 + 1;

        switch (rand() % 4)
        {
        case 0:c = '+'; break;
        case 1:c = '-'; break;
        case 2:c = '*'; break;
        case 3:c = '/'; break;
        }
        fprintf(fp, "%d%c%d=\n", a, c, b);
    }

    fclose(fp);

    return 0;
}
文件格式化 使用案例:四則運算案例(打印運算表達式)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    srand((size_t)time(NULL));
    // 打開文件
    FILE* fp1 = fopen("C:/Users/Administrator/Desktop/xsk1.txt", "r");
    FILE* fp2 = fopen("C:/Users/Administrator/Desktop/xsk2.txt", "w");
    // 判斷
    if (!fp1||!fp2)return -1;

    int a, b, sum;
    char c;

    for (int i = 0; i < 100; i++)
    {
        fscanf(fp1, "%d%c%d\n", &a, &c, &b);

        switch (c)
        {
        case '+':sum = a + b; break;
        case '-':sum = a - b; break;
        case '*':sum = a * b; break;
        case '/':sum = a / b; break;
        }
        fprintf(fp2, "%d%c%d=%d\n", a, c, b,sum);
    }

    fclose(fp1);
    fclose(fp2);
    return 0;
}
文件格式化 使用案例:四則運算案例(打印運算表達式結果)
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 大文件排序 打印1000數字
    srand((size_t)time(NULL));
    // 打開文件
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w");
    // 判斷
    if (!fp)return -1;


    for (int i = 0; i < 1000; i++)
    {
        fprintf(fp, "%d\n", rand() % 256);
    }
    fclose(fp);
    return 0;
}
文件格式化 使用案例:大文件排序(打印1000行數字)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 打開文件
    FILE* fp1 = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
    FILE* fp2 = fopen("C:/Users/Administrator/Desktop/xsk2.txt", "w");
    // 判斷
    if (!fp1||!fp2)return -1;

    int* arr = (int*)malloc(sizeof(int) * 256);

    memset(arr, 0, sizeof(int) * 256);

    // 直接插入
    // 數據一定要在一個范圍內
    for (int i = 0; i < 1000; i++)
    {
        int value;
        fscanf(fp1, "%d\n", &value);
        // 數據的個數放在對應的下標
        arr[value]++;
    }

    for (int i = 0; i < 256; i++)
    {
        for (int j = 0; j < arr[i]; j++)
        {
            fprintf(fp2, "%d\n", i);
        }
    }

    free(arr);
    fclose(fp1);
    fclose(fp2);

    return 0;
}
文件格式化 使用案例:大文件排序(直接插入排序)

文件塊讀寫

一、寫文件

1、說明

#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:以數據塊的方式給文件寫入內容
參數:

  • ptr:准備寫入文件數據的地址
  • size: size_t 為 unsigned int類型,此參數指定寫入文件內容的塊數據大小
  • nmemb:寫入文件的塊數,寫入文件數據總大小為:size * nmemb
  • stream:已經打開的文件指針

返回值:

  • 成功:實際成功寫入文件數據的塊數目,此值和nmemb相等
  • 失敗:0

2、案例

typedef struct Stu
{
       char name[50];
       int id;
}Stu;
 
Stu s[3];
int i = 0;
for (i = 0; i < 3; i++)
{
       sprintf(s[i].name, "stu%d%d%d", i, i, i);
       s[i].id = i + 1;
}
 
int ret = fwrite(s, sizeof(Stu), 3, fp);
printf("ret = %d\n", ret);
fwrite 使用案例

二、讀文件

1、說明

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:以數據塊的方式從文件中讀取內容
參數:

  • ptr:存放讀取出來數據的內存空間
  • size: size_t 為 unsigned int類型,此參數指定讀取文件內容的塊數據大小
  • nmemb:讀取文件的塊數,讀取文件數據總大小為:size * nmemb
  • stream:已經打開的文件指針

返回值:

  • 成功:實際成功讀取到內容的塊數,如果此值比nmemb小,但大於0,說明讀到文件的結尾。
  • 失敗:0

2、案例

typedef struct Stu
{
       char name[50];
       int id;
}Stu;
 
Stu s[3];
int ret = fread(s, sizeof(Stu), 3, fp);
printf("ret = %d\n", ret);
 
int i = 0;
for (i = 0; i < 3; i++)
{
       printf("s = %s, %d\n", s[i].name, s[i].id);
}
fread 使用案例

三、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 寫入數據
    // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "wb");
    // 判斷
    // if (!fp)return -1;
    // int a = 5678;
    // 以二級制格式寫入
    // fwrite(&a, sizeof(int), 1, fp);
    // fclose(fp);
    
    // 數組寫入
    // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "wb");
    // 判斷
    // if (!fp)return -1;
    // int arr[] = { 1,2,3,4,5,6,7,8,10 };
    // fwrite(arr, sizeof(int), 10, fp);
    // fclose(fp);

    // 讀取數據
    // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "rb");
    // 判斷
    // if (!fp)return -1;
    // int value;
    // fread(&value, sizeof(int), 1, fp);
    // printf("%d\n", value);
    // fclose(fp);

    // 數組讀取
    // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "rb");
    // 判斷
    // if (!fp)return -1;
    // int arr[10] = { 0 };
    // fread(arr, sizeof(int), 10, fp);
    // for (int i = 0; i < 10; i++)
    // {
    //     printf("%d\n", arr[i]);
    // }

    return 0;
}
文件塊讀寫 使用案例

文件隨機讀寫

一、說明

#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);

功能:移動文件流(文件光標)的讀寫位置。
參數:

  • stream:已經打開的文件指針
  • offset:根據whence來移動的位移數(偏移量),可以是正數,也可以負數,如果正數,則相對於whence往右移動,如果是負數,則相對於whence往左移動。如果向前移動的字節數超過了文件開頭則出錯返回,如果向后移動的字節數超過了文件末尾,再次寫入時將增大文件尺寸。
  • whence:其取值如下:
  • SEEK_SET:從文件開頭移動offset個字節
  • SEEK_CUR:從當前位置移動offset個字節
  • SEEK_END:從文件末尾移動offset個字節

返回值:

  • 成功:0
  • 失敗:-1

二、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");

    if (!fp)
    {
        return -1;
    }

    char arr[100];

    // 輸出第一行
    memset(arr, 0, 100);
    fgets(arr, 100, fp);
    printf("%s", arr);

    // 輸出第二行
    memset(arr, 0, 100);
    fgets(arr, 100, fp);
    printf("%s", arr);

    // 光標偏移
    // 文件隨機讀寫
    // 從當前位置偏移,往回偏移8個
    fseek(fp, -8, SEEK_CUR);

    // 輸出從光標位置輸出
    memset(arr, 0, 100);
    fgets(arr, 100, fp);
    printf("%s", arr);

    fclose(fp);
    return 0;
}
文件隨機讀寫 使用案例
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r+");

    if (!fp)
    {
        return -1;
    }

    // 從文件末尾追加
    fseek(fp,-1, SEEK_END);

    fputs("aaaa",fp);

    fclose(fp);
    return 0;
}
文件隨機讀寫 使用案例:2

文件流

一、文件流獲取

1、說明

#include <stdio.h>
long ftell(FILE *stream);

功能:獲取文件流(文件光標)的讀寫位置。
參數:

  • stream:已經打開的文件指針

返回值:

  • 成功:當前文件流(文件光標)的讀寫位置
  • 失敗:-1

2、案例

#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "a");

    if (!fp)
    {
        return -1;
    }

    // 查看當前位置
    long pos = ftell(fp);

    printf("%ld\n", pos);

    fclose(fp);
    return 0;
} 
ftell 使用案例

二、文件流修改

1、說明

#include <stdio.h>
void rewind(FILE *stream);

功能:把文件流(文件光標)的讀寫位置移動到文件開頭。
參數:

  • stream:已經打開的文件指針

返回值:
無返回值

2、案例

typedef struct Stu
{
       char name[50];
       int id;
}Stu;
 
//假如已經往文件寫入3個結構體
//fwrite(s, sizeof(Stu), 3, fp);
 
Stu s[3];
Stu tmp;
int ret = 0;
 
//文件光標讀寫位置從開頭往右移動2個結構體的位置
fseek(fp, 2 * sizeof(Stu), SEEK_SET);
 
//讀第3個結構體
ret = fread(&tmp, sizeof(Stu), 1, fp);
if (ret == 1)
{
       printf("[tmp]%s, %d\n", tmp.name, tmp.id);
}
 
//把文件光標移動到文件開頭
//fseek(fp, 0, SEEK_SET);
rewind(fp);
 
ret = fread(s, sizeof(Stu), 3, fp);
printf("ret = %d\n", ret);
 
int i = 0;
for (i = 0; i < 3; i++)
{
       printf("s === %s, %d\n", s[i].name, s[i].id);
}
rewind 使用案例

文件狀態

一、說明

#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);

功能:獲取文件狀態信息
參數:

  • path:文件名
  • buf:保存文件信息的結構體

返回值:

  • 成功:0
  • 失敗-1

二、使用

struct stat {
       dev_t         st_dev;          //文件的設備編號
       ino_t         st_ino;          //節點
       mode_t        st_mode;         //文件的類型和存取的權限
       nlink_t       st_nlink;        //連到該文件的硬連接數目,剛建立的文件值為1
       uid_t         st_uid;          //用戶ID
       gid_t         st_gid;          //組ID
       dev_t         st_rdev;         //(設備類型)若此文件為設備文件,則為其設備編號
       off_t         st_size;         //文件字節數(文件大小)
       unsigned long st_blksize;      //塊大小(文件系統的I/O 緩沖區大小)
       unsigned long st_blocks;       //塊數
       time_t        st_atime;        //最后一次訪問時間
       time_t        st_mtime;        //最后一次修改時間
       time_t        st_ctime;        //最后一次改變時間(指屬性)
};

三、案例

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
 
int main(int argc, char **args)
{
       if (argc < 2)
              return 0;
     
// 文件狀態結構體變量
       struct stat st = { 0 };
     
       stat(args[1], &st);
       int size = st.st_size;//得到結構體中的成員變量
       printf("%d\n", size);
       return 0;
}
stat 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#define MAX (1024*1024*8)

// 拷貝大文件
int main(int argc,char* argv[])
{
    // 顯示參數內容
    //for (int i = 0; i < argc; i++)
    //{
    //    printf("%s\n", argv[i]);
    //}

    // 用戶輸入參數缺少
    if (argc < 3)
    {
        printf("缺少參數\n");
        return -1;
    }

    // C:/copy.exe C:/xsk.txt C:/xsk/xsk.txt
    // argv[0] 程序名稱、文件大小是50M
    FILE* fp1 = fopen(argv[1], "rb");
    FILE* fp2 = fopen(argv[2], "wb");

    if (!fp1 || !fp2)
    {
        printf("賦值文件出錯\n");
        return -2;
    }

    char* temp = NULL;
    int size = 0;

    // 求文件大小
    struct stat st;
    stat(argv[1], &st);

    // 根據文件實際大小開辟空間
    if (st.st_size > MAX)
    {
        temp = (char*)malloc(sizeof(char) * MAX);
        size = MAX;
    }
    else
    {
        temp = (char*)malloc(sizeof(char) * st.st_size + 10);
        size = st.st_size + 10;
    }

    // 接收每次讀取的字節數
    int count = 0;

    while (!feof(fp1))
    {
        memset(temp, 0, size);
        // count=讀取實際字節數、讀取內容
        count = fread(temp, sizeof(char), size,fp1);
        // 根據字節大小寫入
        fwrite(temp, sizeof(char), count, fp2);
    }

    free(temp);
    fclose(fp1);
    fclose(fp2);
    return 0;
}
stat 使用案例:大文件拷貝操作

文件刪除

一、說明

#include <stdio.h>
int remove(const char *pathname);

功能:刪除文件
參數:

  • pathname:文件名

返回值:

  • 成功:0
  • 失敗:-1

二、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 刪除文件
    int value = remove("C:/Users/Administrator/Desktop/xsk.txt");
    if (value == 0)
    {
        printf("刪除成功\n");
    }
    else
    {
        printf("刪除失敗\n");
    }

    return 0;
}
文件刪除 使用案例

文件剪切重命名

一、說明

#include <stdio.h>
int rename(const char *oldpath, const char *newpath);

功能:把oldpath的文件名改為newpath
參數:

  • oldpath:舊文件名
  • newpath:新文件名

返回值:

  • 成功:0
  • 失敗: - 1

二、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 重命名、移動文件
    int value = rename("C:/Users/Administrator/Desktop/xsk.txt","C:/Users/Administrator/Desktop/xsk_new.txt");
    if (value == 0)
    {
        printf("改名成功\n");
    }
    else
    {
        printf("改名失敗\n");
    }
    return 0;
}
文件剪切重命名 使用案例

 


免責聲明!

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



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