fread
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); ?
功能
按塊從文件讀取數據,從文件中讀 nmemb ?個、每個 size ?字節的元素,存入 ptr ?指向的內存。
參數
-? ptr?:存儲讀取數據的內存首地址(需提前分配足夠空間,如定義數組、用 ?malloc??申請堆內存 )。
- ?size?:單個元素的字節數(同 ?fwrite?,需和寫入時的 ?size??一致,否則數據會錯位 )。
- ?nmemb?:希望讀取的元素個數(嘗試讀 ?size * nmemb??字節,實際讀多少看文件內容 )。
- ?stream?:文件流指針(通過 ?fopen??打開,需以可讀模式如 ??"r+"??等打開 )。
返回值
- 成功:返回實際讀到的元素個數(等于 ?nmemb??表示讀滿;若文件末尾不夠 ?nmemb??個元素,返回實際讀到的數量 )。
- 文件末尾:返回 ?0?(可用來判斷是否讀完文件 )。
#include<stdio.h>
struct stu
{int id;char name[100];int score;
};
int main(int argc,const char*argv[])
{FILE*fp = fopen("./1.txt","r");if(NULL == fp){printf("fopen error\n");return -1;}struct stu s;struct stu ss[10];size_t cnt = fread(&s,sizeof(struct stu),1,fp);printf("cnt = %ld\n",cnt);printf("%d %s %d\n",s.id,s.name,s.score);cnt = fread(ss,sizeof(struct stu),10,fp);printf("cnt = %ld\n",cnt);for(int i = 0;i < cnt;i++){printf("%d %s %d\n",ss[i].id,ss[i].name,ss[i].score);}fclose(fp);
}
fwrite
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); ?
功能
按塊向文件寫入數據,把 ptr ?指向的內存數據,以「 size ?字節/元素 、共 nmemb ?個元素」的形式寫入文件。
參數
- ?ptr?:要寫入數據的內存首地址(常搭配數組、結構體等,傳遞 ?&變量??或數組名)。
- ?size?:單個元素的字節數(如 ?sizeof(int)??表示 int 類型占 4 字節)。
- ?nmemb?:要寫入的元素個數(需和 ?size??匹配,總寫入字節 = ?size * nmemb??)。
- ?stream?:文件流指針(通過 ?fopen??打開文件獲得,需確保以可寫模式如 ?"wb"??、?"a+"??等打開 )。
返回值
- 成功:返回實際寫入的元素個數(正常應等于 ?nmemb?;若磁盤滿、權限不足等,可能小于)。
#include<stdio.h>struct stu
{int id;char name[100];int score;
};
int main(int argc,const char*argv[])
{FILE*fp = fopen("./1.txt","w");if(NULL == fp){printf("fopen error\n");return -1;}struct stu ss[5] = {{1,"zahngsan",99},{2,"lisi",90},{3,"wangwu",98},{4,"maliu",67},{5,"wanger",100}};size_t cnt = fwrite(ss,sizeof(struct stu),5,fp);printf("cnt = %ld\n",cnt);fclose(fp);
}
bmp
#pragma pack(1)//bmp文件相關信息
typedef struct tagBITMAPFILEHEADER {short bfType; // 文件類型標志int bfSize; // 文件大小,單位為字節short bfReserved1; // 保留字節short bfReserved2; // 保留字節int bfOffBits; // 數據偏移量,即實際圖像數據開始的位置
}Bmp_file_head_t;
//bmp圖像信息
typedef struct tagBITMAPINFOHEADER {int biSize; // BITMAPINFOHEADER的大小,單位為字節int biWidth; // 位圖的寬度,單位為像素int biHeight; // 位圖的高度,單位為像素short biPlanes; // 目標設備的位平面數,必須為1short biBitCount; // 每像素位數(顏色深度)int biCompression; // 圖像壓縮類型int biSizeImage; // 圖像大小,單位為字節int biXPelsPerMeter;// 水平分辨率,單位為像素/米int biYPelsPerMeter;// 垂直分辨率,單位為像素/米int biClrUsed; // 實際使用顏色數int biClrImportant; // 重要顏色數
}Bmp_info_t;
#pragma pack()int get_bmp_head_info(const char *bmpname, Bmp_file_head_t *pheadinfo, Bmp_info_t *pbmpinfo)
{FILE *fp = fopen(bmpname, "r");if (NULL == fp){printf("fopen error\n");return -1;}fread(pheadinfo, sizeof(Bmp_file_head_t), 1, fp);fread(pbmpinfo, sizeof(Bmp_info_t), 1, fp);fclose(fp);return 0;
}int main(int argc, const char *argv[])
{Bmp_file_head_t headinfo;Bmp_info_t bmpinfo;get_bmp_head_info("./3.bmp", &headinfo, &bmpinfo);printf("sizeof(Bmp_file_head_t) = %ld\n", sizeof(Bmp_file_head_t));printf("sizeof(Bmp_info_t) = %ld\n", sizeof(Bmp_info_t));printf("biWidth = %d, biHeight = %d, biBitCount = %d\n", bmpinfo.biWidth, bmpinfo.biHeight, bmpinfo.biBitCount);return 0;
}
?流定位相關接口
fseek
int fseek(FILE *stream, long offset, int whence);
功能
實現文件流的重新定位,用于調整文件內部指針的位置,決定后續讀寫操作從文件的哪個位置開始。
參數
- ?stream?:需要進行定位操作的文件流指針,由 ?fopen??等函數打開文件后獲得。
- ?offset?:偏移量,用于指定相對于 ?whence??位置移動的字節數,可正(向后移動 ?)、可負(向前移動 ?,但需注意不能越界 )。
- ?whence?:定位的相對基準位置,有以下宏定義可選:
- ?SEEK_SET?:以文件開頭為基準進行偏移,?offset??為相對于文件開頭的偏移字節數。
- ?SEEK_CUR?:以文件當前讀寫位置為基準進行偏移,?offset??是相對于當前位置的偏移量。
- ?SEEK_END?:以文件末尾為基準進行偏移,?offset??常搭配負數,實現從末尾往前定位(如 ?fseek(stream, -10, SEEK_END)??表示定位到文件末尾向前 10 字節處 )。
返回值
- 成功:返回 當前偏移量。
- 失敗:返回 -1 ,常見失敗情況如偏移量導致越界(如 ?SEEK_SET??時 ?offset??為負數 )、文件流異常等。
rewind(fp) ==>fseek(fp,0,SEEK_SET)
ftell
long ftell(FILE *stream);
功能
獲取文件流當前位置到文件開頭的偏移量,即返回當前文件指針距離文件起始位置的字節數,可用于判斷文件大小、輔助 fseek ?定位等場景。
返回值
偏移量:byte
練習
#include<stdio.h>
#include<stdlib.h>
struct stu
{int id;char name[100];int score;
};
int main(int argc,const char*argv[])
{FILE*fp = fopen("./1.txt","w+");if(NULL == fp){printf("fopen error\n");return -1;}struct stu ss[5] = {{1,"zahngsan",99},{2,"lisi",90},{3,"wangwu",98},{4,"maliu",67},{5,"wanger",100}};fwrite(ss,sizeof(struct stu),5,fp);fseek(fp,0,SEEK_END);long len = ftell(fp);rewind(fp);FILE*fp1 = fopen("./2.txt","w");if(NULL == fp1){printf("fopen error\n");return -1;}//空洞文件fseek(fp1,len - 1,SEEK_SET);int ret = fputc('\0',fp1);if(EOF == ret){printf("磁盤空間不足\n");return -1;}fseek(fp1,0,SEEK_SET);char *buff = malloc(len);fread(buff,1,len,fp);fwrite(buff,1,len,fp1);free(buff);fclose(fp);fclose(fp1);
}
strtok
char *strtok(char *str, const char *delim); ?
功能
按分隔符截取字符串,從 ?str??中逐個提取由 ?delim??分隔的子串。首次調用需傳入待分割的完整字符串 ?str?,后續調用傳入 ?NULL??即可繼續分割剩余部分(內部會維護靜態指針記錄位置 )。
參數
- ?str?:
- 首次調用:傳入待分割的原始字符串(會被函數修改,分割后原字符串會被分隔符替換為 ?\0??,用于標記子串結束 )。
- 后續調用:傳入 ?NULL??,函數會基于內部靜態指針,繼續分割剩余未處理的部分。
- ?delim?:
傳入分隔符字符串(如 ?",-"??表示逗號、減號都可作為分隔符 ),只要遇到 ?delim??中任意字符,就會停止當前子串截取。
返回值
- 成功:返回當前截取到的子串首地址(如分割 ?"a,b,c"??,首次返回 ?"a"??的地址,后續依次返回 ?"b"?、?"c"??)。
- 失敗/結束:返回 ?NULL?(當沒有可分割的子串時觸發 )。
練習
實現一個單詞查詢軟件: 用戶從終端輸入一個單詞,查找該單詞的意思并打印; 若用戶輸入".quit",則退出該軟件。
#include<stdio.h>
#include <string.h>
int main(int argc,const char*argv[])
{FILE*fp = fopen("./dict.txt","r");if(NULL == fp){printf("fopen error\n");return -1;}rewind(fp);char s[1024];printf("輸入單詞\n");scanf("%s",s);char buff[1024] = {0};if(0 == strcmp(".quit",s)){return 0; }char *p = fgets(buff,sizeof(buff),fp);while(p != NULL){char *b = strtok(buff," ");if(0 == strcmp(b,s)){b = strtok(NULL,"\r");printf("%s%s\n",s,b);break;}p = fgets(buff,sizeof(buff),fp);}if(p == NULL){printf("not find\n");return 0;}fclose(fp);}