目錄
一、文件分類
1、按存儲(chǔ)介質(zhì)分類
2、按存儲(chǔ)方式分類
二、文本文件
三、二進(jìn)制碼文件?
四、二進(jìn)制和文件文件的區(qū)別?
五、文件緩沖區(qū)?
?1、文件緩沖區(qū)的刷新方式
2、模擬時(shí)鐘
3、文件指針
六、文件的API
1、打開(kāi)文件fopen
2、關(guān)閉文件 fclose
3、逐個(gè)字符讀寫(xiě) fgetc fputc
4、一次讀寫(xiě)一個(gè)字符串 fgets?fputs
5、一次讀寫(xiě)n塊文件數(shù)據(jù) fread?fwrite
?6、格式化讀寫(xiě)?fscanf? fprintf?編輯
?1、格式化寫(xiě)? fprintf ( 文件指針,格式字符串,輸出表列)
2、格式化讀 fscanf ( 文件指針,格式字符串,輸出表列)
七、文件的隨機(jī)讀寫(xiě)
1、順序讀寫(xiě)引入隨機(jī)讀寫(xiě)案例
2、隨機(jī)讀寫(xiě)的API
(1)rewind復(fù)位文件流指針
?(2)ftell返回文件流指針 距離文件首部的 字節(jié)數(shù)
(3)fseek文件流指針定位
八、文件加密器
一、文件分類
1、按存儲(chǔ)介質(zhì)分類
磁盤(pán)文件:文件的數(shù)據(jù) 存放在磁盤(pán)上(音視頻、圖片文件、文檔文件)
設(shè)備文件:通過(guò)系統(tǒng)將外部設(shè)備抽象文件
2、按存儲(chǔ)方式分類
物理上:任何磁盤(pán)文件 在物理上都是二進(jìn)制存儲(chǔ)。
邏輯上:磁盤(pán)文件分為二進(jìn)制文件、文本文件。
二、文本文件
??????? 文本文件基于字符編碼,常見(jiàn)編碼有 ASCII、UNICODE 等。 一般可以使用文本編輯器直接打開(kāi)
????????例如:
? ? ? ? (1)數(shù) 5678 的以 ASCII 存儲(chǔ)形式為?ASCII 碼:
?????????????????00110101(==53=='5')???00110110?? 00110111? ?00111000? ? ? ? ?共4B
? ? ? ? (2)歌詞文件(lrc):文本文件?
三、二進(jìn)制碼文件?
????????基于值編碼,把內(nèi)存中的數(shù)據(jù)原樣輸出到磁盤(pán)上 ,一般需要自己判斷或使用特定軟件分析數(shù)據(jù)格式。
????????例如:數(shù) 5678 的存儲(chǔ)形式為: 二進(jìn)制碼:00010110 00101110
四、二進(jìn)制和文件文件的區(qū)別?
文本文件:
優(yōu)點(diǎn):一個(gè)字節(jié)表示一個(gè)意思、便于查看
缺點(diǎn):空間大、效率低
二進(jìn)制文件:
優(yōu)點(diǎn):效率高、空間小
缺點(diǎn):不定長(zhǎng)、不便于查看
五、文件緩沖區(qū)?
?1、文件緩沖區(qū)的刷新方式
1、行刷新:遇到換行符刷新。
2、滿刷新:緩沖區(qū)數(shù)據(jù)放滿 刷新
3、強(qiáng)制刷新使用fflush函數(shù) 將緩沖刷新
4、關(guān)閉耍新 :程序運(yùn)行結(jié)束的時(shí)候 將緩沖區(qū)數(shù)據(jù) 全部刷新
2、模擬時(shí)鐘
#include<unistd.h>
void test()
{
int i=0;
while(1)
{
printf(\r%02d:%02d",i/60,i%60);//\r回到行首
fflush(stdout);//強(qiáng)制刷新
sleep(1);
i++;
}
3、文件指針
????????所有操作文件的庫(kù)函數(shù) 都需要借助文件指針操作文件。
為每一個(gè)進(jìn)程 默認(rèn)打開(kāi)的3個(gè)文件指針:
(1)stdin:標(biāo)準(zhǔn)輸入默認(rèn)為當(dāng)前終端(鍵盤(pán))
我們使用的scanf、getchar 函數(shù)默認(rèn)從此終端獲得數(shù)據(jù)(2)stdout:標(biāo)準(zhǔn)輸出﹑默認(rèn)為當(dāng)前終端(屏幕)
我們使用的printf、puts 函數(shù)默認(rèn)輸出信息到此終端
(3)stderr:標(biāo)準(zhǔn)錯(cuò)誤輸出設(shè)備文件默認(rèn)為當(dāng)前終端(屏幕)當(dāng)我們程序出錯(cuò)使用:perror函數(shù)時(shí)信息打印在此終端
例:fgets(buf,sizeof(buf),stdin);
? ? ? ? fwrite("hello world",12,1,stdout);//12塊1字節(jié)輸出
六、文件的API
文件的操作步驟:打開(kāi) 讀寫(xiě) 關(guān)閉
1、打開(kāi)文件fopen
? ? ? ? fopen中f描述其為庫(kù)函數(shù),其底層使用open函數(shù)完成系統(tǒng)調(diào)用。
定義:FILE *fopen(const char *path, const char *mode);
path:文件的路徑
mode:打開(kāi)文件方式
返回值:
????????成功:就是打開(kāi)的文件指針
????????失?。篘ULL
文件的打開(kāi)方式mode:r、w、a、+、t、b
r:只讀的方式打開(kāi)
w:只寫(xiě)的方式打開(kāi)
a:追加的方式打開(kāi)(清空重寫(xiě))
+:可讀可寫(xiě)方式打開(kāi)
t:以文本文件方式打開(kāi) (默認(rèn)方式,可省略)
b:以二進(jìn)制方式打開(kāi)(必須顯示說(shuō)明)
?組合方式:
模式 | 功能 |
r或rb | 以只讀方式打開(kāi)一個(gè)文件(不創(chuàng)建文件) |
w或wb | 以寫(xiě)方式打開(kāi)文件(使文件長(zhǎng)度截?cái)酁?字節(jié)(刪除),創(chuàng)建一個(gè)文件) |
a或ab | 以添加方式打開(kāi)文件,即在末尾添加內(nèi)容,當(dāng)文件不存在時(shí),創(chuàng)建文件用于追加寫(xiě)入 |
r+或rb+ | 以可讀、可寫(xiě)的方式打開(kāi)文件(不創(chuàng)建新文件) |
w+或wb+ | 以可讀、可寫(xiě)的方式打開(kāi)文件 (使文件長(zhǎng)度為0字節(jié)(刪除),創(chuàng)建一個(gè)文件) |
a+或ab+ | 以添加方式打開(kāi)文件,打開(kāi)文件并在末尾更改文件(如果文件不存在,則創(chuàng)建文件) |
2、關(guān)閉文件 fclose
定義:int fclose(FILE *fp);
返回值:
????????成功返回? ? ?0
????????失敗返回? 非0
void test()
{
FILE* fp = NULL;
fp = fopen("test.txt", "r");
if (fp = NULL)//文件不存在
{
perror("fopen");
return;
}
fclose(fp);
}
3、逐個(gè)字符讀寫(xiě) fgetc fputc
一次寫(xiě)一個(gè)字節(jié):fputc
函數(shù)的定義:int fputc(int c, FILE *stream)
函數(shù)的說(shuō)明:fputc將c的值寫(xiě)到stream所代表的文件中。
返回值:
????????如果輸出成功,則返回輸出的字節(jié)值;????????如果輸出失敗,則返回一個(gè)EOF。
EOF是在stdio.h文件中定義的宏符號(hào)常量,值為-1,EOF只是在文本文件中有效。
?寫(xiě)入hello world字符串:
void test()
{
FILE* fp = NULL;
fp = fopen("test.txt", "w");
if (fp = NULL)
{
perror("fopen");
return;
}
char* file_data = "hello word";
while (*file_data != '\0')
{
fputc(*file_data, fp);
file_data++;
}
fclose(fp);
}
一次讀一個(gè)字節(jié):fgetc
函數(shù)定義:int fgetc(FILE *stream);
函數(shù)說(shuō)明:fgetc 從stream所標(biāo)示的文件中讀取一個(gè)字節(jié),將字節(jié)值返回
返回值:
????????以t的方式:讀到文件結(jié)尾返回EOF
????????以b的方式:讀到文件結(jié)尾,使用feof函數(shù)(后面會(huì)講)判斷結(jié)尾
?逐個(gè)讀字符串:
void test()
{
FILE* fp = NULL;
fp = fopen("test.txt", "r");
if (fp = NULL)
{
perror("fopen");
return;
}
while(1)
{
char ch = fgetc(fp);
if (ch != EOF)
break;
printf("%c", ch);
}
fclose(fp);
}
4、一次讀寫(xiě)一個(gè)字符串 fgets?fputs
寫(xiě)一個(gè)字符串:int fputs(const char *s, FILE *stream)
讀一個(gè)字符串:char *fgets(char *s, int size, FILE *stream)
讀取一個(gè)字符串(遇到換行符 結(jié)束) ,讀取一行文件數(shù)據(jù)
成功返回目的數(shù)組的首地址,即 s
失敗返回 NULL
?有test.txt文件下讀test.txt文件中數(shù)據(jù)往b.txt中寫(xiě)的測(cè)試程序:
void test06()
{
FILE *fp_r = fopen("test.txt", "r");
if (fp_r == NULL)
{
perror("fopen");
return;
}
FILE *fp_w = fopen("b.txt", "w");
if (fp_w == NULL)
{
perror("fopen");
return;
}
while (1)
{
char buf[128] = "";//存放讀到的數(shù)據(jù)并寫(xiě)到b.txt中
//讀一行
char *ret = fgets(buf, sizeof(buf), fp_r);
if (ret == NULL)
break;
//寫(xiě)一行
fputs(buf, fp_w);
}
fclose(fp_r);
fclose(fp_w);
}
5、一次讀寫(xiě)n塊文件數(shù)據(jù) fread?fwrite
塊寫(xiě):size_t fwrite(void *ptr, size_t size, size_t n, FILE *stream);
函數(shù)說(shuō)明:fwrite 函數(shù)將ptr 指向的內(nèi)存里的數(shù)據(jù),向stream 所標(biāo)示的文件中寫(xiě)入數(shù)據(jù),一塊是size個(gè)字節(jié),共n塊。
塊寫(xiě):將內(nèi)存的數(shù)據(jù) 原樣的寫(xiě)入到 磁盤(pán)文件中
返回值: 實(shí)際寫(xiě)入的塊數(shù)
快寫(xiě)實(shí)例:?
#include <string.h>
typedef struct
{
int num;
char name[30];
}STU;
void test()
{
STU A[3]={{1,"lucy"},{2,"bob"},{3,"張三",{4,"李四"}};
int n = sizeof(hero) / sizeof(hero[0]);
FILE *fp = fopen("S.txt", "w");
if (fp == NULL)
{
perror("fopen");
return;
}
fwrite(A, sizeof(A), n, fp);
fclose(fp);
}
快讀:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
快讀:?磁盤(pán)數(shù)據(jù) 原樣 輸入到 內(nèi)存
返回值: 實(shí)際讀到的整塊數(shù):不足一塊 不計(jì)數(shù) 但數(shù)據(jù)是讀到的。
塊讀實(shí)例?
#include <string.h>
void test02()
{
STU A[3];
memset(A, 0, sizeof(A));
FILE *fp = fopen("S.txt", "r");
if (fp == NULL)
{
perror("fopen");
return;
}
fread(A, sizeof(STU), 3, fp);
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d %s\n", A[i].num, A[i].name);
}
fclose(fp);
}
?6、格式化讀寫(xiě)?fscanf? fprintf
?1、格式化寫(xiě)? fprintf ( 文件指針,格式字符串,輸出表列)
#include <string.h>
typedef struct
{
int num;
char name[30];
}STU;
void test()
{
STU A[3]={{1,"lucy"},{2,"bob"},{3,"張三",{4,"李四"}};
int n = sizeof(hero) / sizeof(hero[0]);
FILE *fp = fopen("S.txt", "w");
if (fp == NULL)
{
perror("fopen");
return;
}
//格式化寫(xiě)
int i = 0;
for (i = 0; i < n; i++)
{
fprintf(fp, "%s %d \n", A[i].num, A[i].name);
}
fclose(fp);
}
2、格式化讀 fscanf ( 文件指針,格式字符串,輸出表列)
#include <string.h>
void test02()
{
STU A[3];
memset(A, 0, sizeof(A));
FILE *fp = fopen("S.txt", "r");
if (fp == NULL)
{
perror("fopen");
return;
}
int i = 0;
for (i = 0; i < 3; i++)
{
fscanf(fp, "%d %s",&A[i].num, A[i].name);
}
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d %s\n", A[i].num, A[i].name);
}
fclose(fp);
}
七、文件的隨機(jī)讀寫(xiě)
文件默認(rèn)是流指針順序讀寫(xiě),讀寫(xiě)順序移動(dòng)流指針 用戶不能更改。
?????????????????????????????隨機(jī)讀寫(xiě):用戶可以更改文件流指針的位置
1、順序讀寫(xiě)引入隨機(jī)讀寫(xiě)案例
void test()
{
FILE* fp = NULL;
fp = fopen("test.txt", "w+");
if (fp = NULL)
{
perror("fopen");
return;
}
fpus("hello world", fp);//此時(shí)流指針指向該字符串末尾
char buf[100] = "";
//讀時(shí)從流指針開(kāi)始往后順序讀,會(huì)讀不到字符串hello world
fgets(buf, sizeof(buf), fp);
printf("讀到的數(shù)據(jù):%s\n", buf);//無(wú)數(shù)據(jù)顯示
fclose(fp);
}
順序讀寫(xiě)解決該問(wèn)題:文件關(guān)閉重新打開(kāi)后流指針會(huì)復(fù)位。但文件會(huì)打開(kāi)兩次關(guān)閉兩次。
void test()
{
FILE* fp = NULL;
fp = fopen("test.txt", "w+");
if (fp = NULL)
{
perror("fopen");
return;
}
fpus("hello world", fp);//此時(shí)流指針指向該字符串末尾
//流指針復(fù)位
fclose(fp);
fp=fopen("test.txt","r");
//讀取數(shù)據(jù)
char buf[100] = "";
fgets(buf, sizeof(buf), fp);
printf("讀到的數(shù)據(jù):%s\n", buf);
fclose(fp);
}
2、隨機(jī)讀寫(xiě)的API
(1)rewind復(fù)位文件流指針
void rewind(FILE *stream);
void test()
{
FILE* fp = NULL;
fp = fopen("test.txt", "w+");
if (fp = NULL)
{
perror("fopen");
return;
}
fpus("hello world", fp);//此時(shí)流指針指向該字符串末尾
//復(fù)位文件流指針
rewind(fp);
//讀取數(shù)據(jù)
char buf[100] = "";
fgets(buf, sizeof(buf), fp);
printf("讀到的數(shù)據(jù):%s\n", buf);
fclose(fp);
}
?(2)ftell返回文件流指針 距離文件首部的 字節(jié)數(shù)
long ftell(FILE *stream);
void test()
{
FILE* fp = NULL;
fp = fopen("test.txt", "w+");
if (fp = NULL)
{
perror("fopen");
return;
}
fpus("hello world", fp);//此時(shí)流指針指向該字符串末尾
//復(fù)位文件流指針
long len=ftell(fp);
printf("文件的大?。?ld\n", len);
fclose(fp);
}
(3)fseek文件流指針定位
int fseek(FILE *stream, long offset, int whence);
?whence 定位流指針的起始位置
????????????????文件開(kāi)頭 SEEK_SET 0
????????????????文件當(dāng)前位置 SEEK_CUR 1
????????????????文件末尾 SEEK_END 2
offset:流指針的偏移量,如果為正數(shù)向右偏移(單位為字節(jié)數(shù))為負(fù)數(shù)就是向左偏移
案例:一次性讀取文件數(shù)據(jù)
主要步驟:
(1)將文件流指針定位到尾部
(2)ftell返回文件流指針的偏移量 (文件總大小len)
(3)根據(jù)文件總大小 從堆區(qū)申請(qǐng)空間 len+1
(4)使用fread一次性將文件數(shù)據(jù)讀取?
?實(shí)現(xiàn)代碼:
#include <stdlib.h>
#include <string.h>
void test06()
{
FILE *fp = fopen("c.txt", "r");
if (fp == NULL)
{
perror("fopen");
return;
}
fseek(fp, 0, 2);
long len = ftell(fp);
//復(fù)位文件流指針
rewind(fp);
printf("文件總大小:len=%ld\n", len);
unsigned char *text = (unsigned char *)calloc(1, len + 1);
fread(text, len, 1, fp);
printf("%s\n", text);
fclose(fp);
//釋放堆區(qū)空間(不是必須操作)
if (text != NULL)
{
free(text);
text = NULL;
}
}
八、文件加密器
main.c
#include <stdio.h>
#include <stdlib.h>
#include "fun.h"
int main(int argc ,char *argv[])
{
while(1)
{
int cmd=0;
print_help();
printf("請(qǐng)輸入指令:");
scanf("%d",&cmd);
if(cmd==1)
{
char dest_file[31]="";
char src_file[31]="";
unsigned long file_length=0;
char *read=NULL;
unsigned int password=0;
//從鍵盤(pán)獲取源文件和目的文件名字
get_file_name(dest_file,src_file);
//從文件中讀出內(nèi)容
read = read_src_file(&file_length,src_file);
//獲取加密password
printf("請(qǐng)輸入密碼:");
scanf("%u",&password);
//字符數(shù)組加密
read=file_text_encrypt(read,file_length,password);
//保存文件
save_file(read,file_length,dest_file);
}
else if (cmd==2)
{
char dest_file[31]="";
char src_file[31]="";
unsigned long file_length=0;
char *read=NULL;
unsigned int password=0;
//從鍵盤(pán)獲取源文件和目的文件名字
get_file_name(dest_file,src_file);
//從文件中讀出內(nèi)容
read = read_src_file(&file_length,src_file);
//獲取加密password
printf("請(qǐng)輸入密碼:");
scanf("%u",&password);
//字符數(shù)組加密
read=file_text_decrypt(read,file_length,password);
//保存文件
save_file(read,file_length,dest_file);
}
else if (cmd==3)
{
break;
}
else
{
printf("輸入指令出錯(cuò)!?。n");
}
}
return 0;
}
?fun.c文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-609191.html
#include <stdio.h>
#include <stdlib.h>
void print_help()
{
printf("********1:加密文件***********\n");
printf("********2:解密文件***********\n");
printf("********3:退出程序***********\n");
}
void get_file_name(char * dest_file_name,char * src_file_name)
{
printf("請(qǐng)輸入源文件的名稱:");
scanf("%s",src_file_name);
printf("請(qǐng)輸入目的文件的名稱:");
scanf("%s",dest_file_name);
return;
}
char *read_src_file(unsigned long *file_length,char *src_file_name)
{
char *data=NULL;
FILE *fp;
fp=fopen(src_file_name,"r");//只讀的方式打開(kāi)文件
if(fp==NULL)
{
perror("fopen");
return NULL;
}
//流指針go尾部
fseek(fp,0,2);
//流指針的偏移量
*file_length = ftell(fp);
//流指針復(fù)位
rewind(fp);
//申請(qǐng)空間保存文件
data=(char *)calloc(1,*file_length);
if(NULL==data)
{
perror("calloc");
return NULL;
}
//一次性讀
fread(data,*file_length,1,fp);
fclose(fp);
return data;
}
char *file_text_encrypt(char * src_file_text,unsigned long int length,unsigned int password)
{
char *data=NULL;
unsigned int i=0;
for(i=0;i<length;i++)
{
src_file_text[i] += password;
}
return src_file_text;
}
void save_file(char* text,unsigned long int length,char * file_name)
{
char *data=NULL;
FILE *fp;
fp=fopen(file_name,"w");
if(NULL==fp)
{
perror("fp");
return;
}
//寫(xiě)
fwrite(text,length,1,fp);
fclose(fp);
if(text !=NULL)
{
free(text);
text =NULL;
}
return;
}
char *file_text_decrypt(char * src_file_text,unsigned long int length,unsigned int password)
{
char *data=NULL;
unsigned int i=0;
for(i=0;i<length;i++)
{
src_file_text[i] -= password;
}
return src_file_text;
}
?fun.h文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-609191.html
#ifndef __FUN_H__
#define __FUN_H__
extern void print_help();
extern void get_file_name(char * dest_file_name,char * src_file_name);
extern char *read_src_file(unsigned long *file_length,char *src_file_name);
extern char *file_text_encrypt(char * src_file_text,unsigned long int length,unsigned int password);
extern void save_file(char* text,unsigned long int length,char * file_name);
extern char *file_text_decrypt(char * src_file_text,unsigned long int length,unsigned int password);
#endif
到了這里,關(guān)于【C語(yǔ)言】高效處理文件內(nèi)容:C語(yǔ)言的文件操作技巧與竅門(mén)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!