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; }
二、文件結尾
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; }
四、案例

#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; }
二、讀文件
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; }
三、案例

#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; }
三、案例

#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; }

#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);
二、讀文件
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); }
三、案例

#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; }
文件流
一、文件流獲取
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; }
二、文件流修改
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); }
文件狀態
一、說明
#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; }

#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; }
文件刪除
一、說明
#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; }