microstation添加txt文件_C开发实战-文件操作

文件概述

文件几乎无处不在,主要分为磁盘文件和设备文件,典型的磁盘文件有文本文件和二进制文件,磁盘文件存储在外部存储介质(例如磁盘,硬盘,U盘等等)需要加载到内存中才能使用。
无论是文本文件还是二进制文件在计算机内部都是以字节为单位,二进制的方式存储。

  • 文本文件存储的是字符对应的ASCII码值,例如文本字符的a在计算机内部就是以二进制01100001 即97存储。当使用文本编辑器(例如Visual Studio Code)打开文本文件时,会将文本文件的二进制转换成ASCII编码对应的字符。
  • 二进制文件存和取的是二进制数值,常见的二进制文件有图片、音频、视频等等。二进制文件不能使用文本编辑器(例如Visual Studio Code)打开,图片需要使用特定的软件(例如Windows的照片浏览器)打开。

设备文件有标准输入文件(stdin),标准输出文件(stdout),标准错误(stderr)三个文件,设备文件在程序启动时由系统默认打开,程序员无需调用fopen(stdin/stdout/stderr,"r+")函数打开这三个设备文件即可使用。

  • stdin: 标准输入,默认为当前终端(键盘),我们使用的scanf、getchar函数默认从此终端获得数据。
  • stdout:标准输出,默认为当前终端(屏幕),我们使用的printf、puts函数默认输出信息到此终端。
  • stderr:标准出错,默认为当前终端(屏幕),我们使用的perror函数默认输出信息到此终端。

文件流指针

当打开文件时,系统内核会返回一个FILE结构体,该结构体有对文件操作的所有信息。

typedef struct{short           level;//缓冲区"满"或者"空"的程度 unsigned        flags;//文件状态标志 char            fd;//文件描述符unsigned char   hold;//如无缓冲区不读取字符short           bsize;//缓冲区的大小unsigned char   *buffer;//数据缓冲区的位置 unsigned        ar; //指针,当前的指向 unsigned        istemp;//临时文件,指示器short           token;//用于有效性的检查 }FILE;

而当调用fopen()函数时,系统会返回这个FILE结构体的地址,即 FILE * p; ,当使用函数fputc('a',p)往文件写入字符时,只需要传递文件流指针p即可。
文件流指针和之前的指针不同的是无法通过*p获取文件内容。

文件的打开和关闭

文件的打开

C语言提供了fopen()函数用于打开文件,该函数的声明位于stdio.h头文件中,fopen()调用时需要两个参数:路径名和打开的方式,如果是当前路径以./表示,Visual Studio2019 本地Windows调试器运行时源文件file_open_close.c的当前目录是D:workspacecittimelinedotnetvs2019c-corec-core-advanced,打开方式可以是如下几种方式

  • r或rb 以只读方式打开一个文本文件(不创建文件,若文件不存在则报错)
  • w或wb 以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)
  • a或ab 以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件
  • r+或rb+ 以可读、可写的方式打开文件(不创建新文件)
  • w+或wb+ 以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)
  • a+或ab+ 以添加方式打开文件,打开文件并在末尾更改文件,若文件不存在则创建文件

其中w选项如果文件不存在会创建文件,但是如果文件有内容会清空。r选项文件不存在,则不创建文件。而b表示打开二进制文件。
fopen()打开文件成功后返回FILE*p结构体的地址,也标识了那个文件,操作指针就是操作那个文件。打开失败返回NULL。

以只读的方式打开当前路径下的test.txt文件

#define _CRT_SECURE_NO_WARNINGS#include #include /*  以只读方式打开当前目录的test.txt文本文件*/void readonly_open_txt() {FILE* p_readonly = fopen("./test.txt", "r");if (p_readonly == NULL) {//追加错误提示前缀perror("readonly mode open file");return;}}/*文件的打开和关闭  fopen()函数打开方式说明 r或rb以只读方式打开一个文本文件(不创建文件,若文件不存在则报错) w或wb以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) a或ab以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件 r+或rb+以可读、可写的方式打开文件(不创建新文件) w+或wb+以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) a+或ab+以添加方式打开文件,打开文件并在末尾更改文件,若文件不存在则创建文件@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int file_open_close_main(int argc, char* argv[]){readonly_open_txt();system("pause");return 0;}

因为当前路径下不存在test.txt文件,所以程序运行时会出现错误提示

c4d83bb0b22ff7c937858f9616124797.png

以只写的方式打开当前目录下的test.txt文本文件,如果文件不存在则会创建文件,打开成功返回FILE *p_write

#define _CRT_SECURE_NO_WARNINGS#include #include /* 以只写的方式打开当前目录下的test.txt文本文件,如果文件不存在则会创建文件,打开成功返回FILE *p_write*/FILE*  write_open_txt() { FILE* p_write = fopen("./test.txt", "w"); if (p_write == NULL) {  perror("write mode open file");  return; } else { printf("open test.txt success!"); } return p_write;}/*文件的打开和关闭  fopen()函数打开方式说明 r或rb以只读方式打开一个文本文件(不创建文件,若文件不存在则报错) w或wb以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) a或ab以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件 r+或rb+以可读、可写的方式打开文件(不创建新文件) w+或wb+以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) a+或ab+以添加方式打开文件,打开文件并在末尾更改文件,若文件不存在则创建文件@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){FILE* p_write = write_open_txt();system("pause");return 0;}
e83bfbb720524103dccc7895e8437a82.png

程序运行结果


以只写方式打开时如果test.txt文件不存在,系统会创建文件

74d0a483f7c7a43d4f4859e6026d7b9d.png

文件的关闭

C语言提供了fclose()函数用于关闭文件,该函数的声明也位于stdio.h头文件中,fclose()函数需要的参数就是打开文件返回的文件流指针,通常情况下文件打开后如果操作完成应该就要关闭。如果文件只打开而不关闭,会给程序造成异常。系统设置了一个应用程序只能打开1024个文件。

以只写的方式打开当前系统路径下的文本文件test.txt 后关闭文件

#define _CRT_SECURE_NO_WARNINGS#include #include /*以只写的方式打开当前目录下的test.txt文本文件,如果文件不存在则会创建文件,打开成功返回FILE *p_write*/FILE*  write_open_txt() {FILE* p_write = fopen("./test.txt", "w");if (p_write == NULL) {perror("write mode open file");return;}return p_write;}/*文件的打开和关闭  fopen()函数打开方式说明 r或rb以只读方式打开一个文本文件(不创建文件,若文件不存在则报错) w或wb以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) a或ab以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件 r+或rb+以可读、可写的方式打开文件(不创建新文件) w+或wb+以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) a+或ab+以添加方式打开文件,打开文件并在末尾更改文件,若文件不存在则创建文件@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){FILE *p_write=write_open_txt();//关闭文件fclose(p_write);system("pause");return 0;}

文件的顺序读写

基于字符写文件

C语言提供了fputc()函数实现写入单个字符到文件中,该函数需要两个参数:字符和文件流指针。写入成功会返回写入的字符,如果写入失败则返回-1

#define _CRT_SECURE_NO_WARNINGS#include #include /*以字符的方式写入文件*/void write_file_char() {//以写的方式打开当前目录下的test.txt文件FILE* p_write = fopen("./test.txt","w");if (NULL==p_write) {perror("write mode open fail");return;}//将字符a写入当前目录下的test.txt文件char c=fputc('a', p_write);printf("写入test.txt文本文件的字符内容是%c",c);}/*基于字符的文件写操作@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){write_file_char();system("pause");return 0;}

程序运行结果

8396d5033a17f8559003d6634035d1bb.png

查看当前目录D:workspacecittimelinedotnetvs2019c-corec-core-advanced 下test.txt文件的内容

e43ad5e583dac165acd7007ef0faf9d1.png

需要注意的是fputc()函数在写入字符前,默认会清空文件的内容,如果要是追加文件,将打开文件的打开方式改成追加即可。

//以追加的方式打开当前目录下的test.txt文件FILE* p_append = fopen("./test.txt","a");

而如果想要往文件追加写入字符串,借助循环就可以搞定

#define _CRT_SECURE_NO_WARNINGS#include #include /*以追加的方式将字符写入test.txt文本文件中*/void append_file_str() {FILE* p_append = fopen("./test.txt", "a");if (NULL == p_append) {perror("write mode open fail");return;}//以追加的方式将字符串hello world写入test.txt文本文件中char buf[] = "hello world";int i = 0;while (buf[i] != 0) {fputc(buf[i], p_append);i++;}}/*基于字符的文件写操作@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){append_file_str();system("pause");return 0;}
947e71cd2fa3ff015a456fcdfa6dac2e.png

写入字符串

基于字符读文件

C语言提供了fgetc()函数实现基于字符从字符流指针中读取文件,该函数的参数只需要传递文件流指针即可,读取成功会返回读取的字符,读取失败返回-1。

#define _CRT_SECURE_NO_WARNINGS#include #include char buf[128] = "";/*读取指定路径的文件并返回char**/char * read_text_by_char(char *path) {//以只读的方式打开当前路径下的test.txt文件FILE *p_readonly=fopen(path,"r");if (NULL==p_readonly) {perror("read file error");return NULL;}int i= 0;//EOF 表示-1 即当没有读取失败时将读取的值赋值给buf[i ]//fgetc()的返回值是-1表示失败,当读取的文件中有-1时,就会提前结束,因此不能使用EOFwhile ((buf[i++] = fgetc(p_readonly)) != EOF);return &buf;}/*基于字符读取文件@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){char *buffer=read_text_by_char("./test.txt");printf("test.txt content is %s", buffer);system("pause");return 0;}

程序运行结果

7ea99398371ded4071f9f188c9112fed.png

fgetc()函数在基于字符读取文件时,如果文件内容有-1这种数字,就不能使用EOF作为文件的结尾。

为了解决这个问题,C语言提供了feof()函数用于检测是否读到了文件的结尾。即判断最后一次读操作的内容不是当前位置的内容(上一个内容),该函数的返回值如果是0就表示没有到文件结尾,如果是非0就表示到文件结尾。

#define _CRT_SECURE_NO_WARNINGS#include #include char buf[128] = "";/*使用feof()函数判断文件是否读取完毕,解决了fgetc()函数读取-1字符的二进制返回-1时读取就停止的问题*/char* read_text(char * path) {//以只读的方式打开当前路径下的test.txt文件FILE* p_readonly = fopen(path, "r");if (NULL == p_readonly) {perror("read file error");return NULL;}int i = 0;int pos = 0;do {buf[i] = fgetc(p_readonly);i++;pos = feof(p_readonly);// pos ==0 表示没有到文件末尾} while (pos==0);return buf;}/*基于字符读取文件@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){char *buffer=read_text("./test.txt");printf("test.txt content is %s", buffer);system("pause");return 0;}

基于字符文件的拷贝

文件的拷贝就是将一个文件创建一个副本。
而文本文件的拷贝的实现过程就是首先读取一个文件,然后将读取的文件内容写入到待拷贝的文件中。

我这里封装了一个函数 copy_text_file(char* source_path,char *target_path) ,只需要传递源文件和目标文件就可以实现文件的拷贝

#define _CRT_SECURE_NO_WARNINGS#include #include /*封装一个文本文件的拷贝方法,传递两个文件的路径实现将source_path的文件内容拷贝到target_path*/void copy_text_file(char* source_path,char *target_path) {FILE* source = fopen(source_path,"r");if (NULL == source) {perror("open file  error");}FILE* target = fopen(target_path,"w");if (NULL == target) {perror("open file target.txt error");}char ch = 0;while (1) {//读取文件的内容ch=fgetc(source);//读取到函数的末尾if (feof(source)) {break;}//将读取的文件内容写入到target文件指针fputc(ch, target);}//关闭文件fclose(target);fclose(source);}/*实现文件拷贝@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){copy_text_file("./test.txt","./target.txt");system("pause");return 0;}

程序运行结果
查看拷贝的源文件和目标文件的内容

158f147ae8c05a28a2767bf1a75bab7b.png

但是copy_text_file(char* source_path,char *target_path)函数只能实现文本文件的拷贝,如果想要实现二进制文件(例如图片)的拷贝,需要稍微改造下fopen()方法

#define _CRT_SECURE_NO_WARNINGS#include #include /*二进制文件的复制*/void copy_binary_file(char* source_path, char* target_path) {FILE* source = fopen(source_path, "rb");if (NULL == source) {perror("open file  error");}FILE* target = fopen(target_path, "wb");if (NULL == target) {perror("open file target.txt error");}char ch = 0;while (1) {//读取文件的内容ch = fgetc(source);//读取到函数的末尾if (feof(source)) {break;}//将读取的文件内容写入到target文件指针fputc(ch, target);}//关闭文件fclose(target);fclose(source);}/*实现文件拷贝@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){copy_binary_file("./20201129.jpg","./20201129_copy.jpg");system("pause");return 0;}

程序运行结果

51a283663f4d332409a54aae2808288c.png

基于字符的文件查看

将指定的文件内容写入到终端

#define _CRT_SECURE_NO_WARNINGS#include #include void cat_file(char* file_path) {//以只读方式打开当前目录的text_file_cat.c文件FILE *p=fopen(file_path,"r");if (NULL==p) {perror("file read error");return;}char ch = 0;while (1) {//读取指定的内容ch = fgetc(p);//如果读到文件末尾if (feof(p)) {break;}//将读取的文件内容写入到终端 //stdout表示终端的文件流指针//printf()底层会调用fputc()fputc(ch,stdout);}//关闭文件fclose(p);}/*文本文件查看@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){cat_file("text_file_cat.c");return 0;}

程序运行结果

467f43ef0ffaa1424a38f5d8b0cb04f9.png

基于行写文件

C语言提供了fputs(const char*str,FILE *stream)函数用于将字符串写入到指定的文件,其中str是待写入文件的字符串地址,stream表示文件流指针,字符串结束符 '0' 停止写入,写入成功返回0,写入失败返回-1。

#define _CRT_SECURE_NO_WARNINGS#include #include /*fputs()写入字符串到指定的文件@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){//以只写的方式打开当前路径下的test.txtFILE* p = fopen("test.txt","w");if (NULL==p) {perror("open file fail");}char buf[] = "I will see you again0again ";//将字符串I will see you again 写入到test.txt文件中//遇到0停止写入int result = fputs(buf,p);if (result==0) {printf("写入数据成功");}else {printf("写入数据失败");}system("pause");return 0;}

程序运行结果

7d1a777b40681e7130e7b2ff9a427942.png

基于行读文件

C语言提供了fgets(char* str, int size ,FILE *stream)函数用于从文件读取字符串,其中str用于保存读取的内容,而size是指定最大读取字符串的长度(size-1),stream表示文件流指针。fgets()函数遇到会结束。
读取成功则返回读取的字符串,读取到文件末尾或则失败则返回NULL。需要注意的是 fgets()函数只能操作字符串,不能操作二进制文件。

#define _CRT_SECURE_NO_WARNINGS#include #include /*基于fgets()读取指定文件的字符串@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){FILE* p = fopen("./test.txt", "r");if (NULL == p) {perror("读取文件错误");return;}char buf[1024] = "";fgets(buf, sizeof(buf), p);printf("buf = %s ", buf);system("pause");return 0;}

程序运行结果

c07d64f7eb0deed050c785a52a2f8ef8.png

基于fputs()函数和fgets()函数实现的文本文件拷贝

#define _CRT_SECURE_NO_WARNINGS#include #include #include /*基于fputs()和fgets()函数实现的文件拷贝 只能支持文本文件,因为遇到0会停止读写*/void copy_by_fgets_fputs(char * source_path,char *target_path) {FILE* source = fopen(source_path,"r");if (NULL==source) {perror("open file fail");return;}FILE* target = fopen(target_path,"w");if (NULL == target) {perror("open file fail");return;}char* p = NULL;//循环多少次,buf就可以使用多少次char buf[1024] = "";while (1) {memset(buf, 0, sizeof(buf));p = fgets(buf, sizeof(buf), source);//读取结束if (p==NULL) {break;}//将读取的内容写入到targetfputs(buf, target);}//fclose(target);fclose(source);}/*基于fputs()和fgets()函数实现的文件内容拷贝@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){copy_by_fgets_fputs("./test.txt","./copy_of.txt");system("pause");return 0;}
d277e0bf56b385c26ecffa40e2dadb1e.png

程序运行结果

基于文件读写实现随机生成表达式并完成四则运算

首先定义一个宏,用于描述生成表达式的数量

//表达式生成的数量#define EXPRESSION_NUM 10

由于生产表达式,需要读写文件,在读写文件之前,需要打开文件,因此封装一个打开文件的函数,该函数需要一个参数:打开方式
而FILE_PATH 也是宏定义的文件路径#define FILE_PATH "expression_calc.txt",算术运算表达式就是存储在该文件中。

/*按照指定的打开方式打开指定路径的文件*/FILE* open_file(char * mode) {FILE* fp=fopen(FILE_PATH, mode);if (NULL==fp) {perror("open file fail");return;}return fp;}

然后实现生成表达式的函数。以及将生成的表达式写入文件中。
这其中表达式的操作数和运算符都是是随机生成的,需要借助srand()函数和rand()函数。
然后还要使用sprintf()函数组包生成表达式。

/*生成表达式并写入文件*/void generator_expression_write_file() {FILE *fp=open_file("w");//设置随机种子srand(time(NULL));int left = 0;int right = 0;char opertors[4] = {'+','-','*','/'};char operator_index=0;char singleton_expression[128] = "";//生成10个随机表达式字符串for (int i = 0; i < EXPRESSION_NUM;i++) {//产生1-100之间的随机数left= rand()%100+1;right= rand()%100+1;//产生0-3之间的随机数赋值给operator_indexoperator_index =rand() % 4;//将 "%d %c %d = ",left, opertors[operator_index],right 赋值给expressionsprintf(singleton_expression,"%d%c%d=",left, opertors[operator_index],right);fputs(singleton_expression, fp);}fclose(fp);}

然后实现读取文件后计算表达式,并将表达式的结果写入FILE_PATH中。

/*计算表达式的结果并写入文件*/void calc_expression_write_file() {FILE* fp = open_file("r");//第一个操作数int left = 0;//第二个操作数int right = 0;//运算符char operator=0;//运算的结果int result = 0;//读取的单个表达式(未计算)char buf[128] = "";//单个表达式(已经计算结果的)char singleton_expression[128] = "";//所有的表达式char all_expression[100][128] = { 0 };//读取一行表达式的指针char* p = NULL;int i = 0;printf("生成的表达式列表");while (1) {//每次读取一行p = fgets(buf, sizeof(buf), fp);if (p == NULL) {break;}//将读取的内容buf 解析到left, operator,right变量中sscanf(buf, "%d%c%d", &left, &operator,&right);//根据运算的符来进行运算并保存运算的结果switch (operator) {case '+':result = left + right;break;case '-':result = left - right;break;case '*':result = left * right;break;case '/':result = left + right;break;}//2+3=5//将表达式以及计算的结果写入all_expression二维数组中sprintf(all_expression[i], "%d%c%d=%d", left, operator,right, result);printf("%s ",  all_expression[i]);i++;}//关闭文件fclose(fp);//FILE *n_fp = open_file("w");for (int j = 0; j < i; j++) {int result =fputs(all_expression[j], n_fp);if (result==0) {printf("写入%s到文件%s成功", all_expression[j],FILE_PATH);}else {printf("写入%s到文件%s失败", all_expression[j], FILE_PATH);}}fclose(n_fp);}

最后在main函数中依次调用这两个函数并运行即可

#define _CRT_SECURE_NO_WARNINGS#include#include#include#include //表达式生成的数量#define EXPRESSION_NUM 10#define FILE_PATH "expression_calc.txt"/*基于文件读写实现随机生成表达式并完成四则运算@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){generator_expression_write_file();calc_expression_write_file();system("pause");return 0;}

程序运行结果

58c5efff9eec1100d1d01f6d4cf662da.png

程序运行结果

a70c2d082983ae86033dfd3b45620144.png

基于指定格式写文件

C语言提供了fprintf(FILE * stream, const char * format, ...)函数用于将数据按照指定的格式写入到指定的文件中,其中stream表示文件流指针,而format就是数据的格式,...表示需要组装的数据列表。
fprintf()函数写入成功则会返回实际写入的字符个数,如果写入失败则返回-1。

#define _CRT_SECURE_NO_WARNINGS#include #include /*fprintf()函数按照指定的格式写入数据到文本文件@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){char name[] = "刘光磊";double height = 178.00;int age = 28;FILE* fp = fopen("./info.txt","w");if (NULL==fp) {perror("read file fail");return -1;}fprintf(fp, "我的名字是%s我的身高是%.2lf我的年龄是%d", name, height, age);fclose(fp);system("pause");return 0;}

程序运行结果

6264bd02985f131cc71de3120578a73e.png

程序运行结果

基于指定格式读文件

C语言提供了fscanf(FILE * stream, const char * format, ...);函数用于从文件中按照指定的格式来读取数据,读取成功返回成功转换参数的个数,失败返回-1。

#define _CRT_SECURE_NO_WARNINGS#include #include /*使用fscanf()从文件中读取指定格式的数据@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){int year = 0;int month = 0;int day = 0;FILE* fp = fopen("./date.txt", "r");if (NULL == fp) {perror("read file fail");return -1;}//从date.txt文件中读取日期并赋值给year,month,dayfscanf(fp, "%d-%d-%d", &year, &month, &day);printf("year = %d",year);printf("month = %d", month);printf("day = %d", day);system("pause");return 0;}

读取的文件内容

259f6b20e043c69acf620af44e3bbd01.png

程序运行结果

ecb23ea0a1d0a58f7b7f1a8260109cb9.png

基于块写文件

在读写大文件时需要基于块来读写文件,C语言提供了fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);函数来基于块写文件,其中ptr表示写入文件数据的地址,size表示写入文件内容的大小,nmemb表示写入文件的块数,写入文件的总大小为szie * nmemb,stream表示已经打开的文件流指针。写入成功则返实际成功写入文件数据的块数目,该值和nmemb相等。

将结构体数组user_array以块的形式写入fwrite.txt文件

#define _CRT_SECURE_NO_WARNINGS#include #include //定义一个结构体user,别名是userstypedef struct user {int id;char name[16];}users;/*fwrite()函数:基于块写文件@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){//初始化一个结构体数组users user_array[3] = { {1,"tony"},{2,"mengmeng"},{3,"xiaohuihui"} };FILE* fp = fopen("fwrite.txt","w");if (NULL==fp) {perror("open file fail");return -1;}//fwrite()第二个参数写1,返回值刚好是写入文件的字节数int byte_size=fwrite(user_array, 1, sizeof(user_array), fp);printf("写入文件的字节数是%d",byte_size);system("pause");return 0;}

基于块读文件

C语言提供了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

实现读取fwrite.txt文件的内容,由于该文件的内容是一个结构体数组,因此需要在头文件user.h中定义一个通用的结构体,其他的源文件使用该结构体时包含#include "user.h"即可

#pragma once//定义一个结构体user,别名是userstypedef struct user {int id;char name[16];}users;

然后使用fread()函数读取文件内容并存储到结构体数组中,然后遍历结构体数组的内容,显示在终端上。

#define _CRT_SECURE_NO_WARNINGS#include #include #include "user.h"#include /*fread()基于块的方式读取文件@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){users user_array[3];//将数组清零memset(user_array, 0, sizeof(user_array));int size = sizeof(user_array) / sizeof(user_array[0]);FILE* fp = fopen("./fwrite.txt","r");//一次性读到user_arrayfread(&user_array, 1, sizeof(user_array), fp);for (int i = 0; i < size;i++) {//从fp读取一个结构体users并赋值给&user_array[i]//fread(&user_array[i], 1, sizeof(users), fp);printf("id = %d name = %s ",user_array[i].id,user_array[i].name);}system("pause");return 0;}

程序运行效果

45c40e98d9338a4297dbcf2f1f7ec732.png

文件的随机读写

之前介绍的读写文件函数都是顺序读写的。

C语言提供了fseek(FILE *stream, long offset, int whence) 函数实现移动文件流(文件光标)的读写位置实现随机读写。

  • fseek(fp,6,SEEK_SET)表示光标相对于开头向后移动6个字节
  • fseek(fp,0,SEEK_SET)表示光标移动至开头
  • fseek(fp,4,SEEK_CUR)表示光标相对当后移动4个字节
  • fseek(fp,-4,SEEK_CUR)表示光标相对当前移动4个字节
  • fseek(fp,4,SEEK_END)表示光标相对末尾往后移动4个字节

除此以外C语言还提供了rewind(fp)函数将光标移到开头,等价于fseek(fp,0,SEEK_SET),ftell(fp)函数可以获取文件流(文件光标)的读写位置。

#define _CRT_SECURE_NO_WARNINGS#include #include #include /*fseek()随机读写@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){FILE* fp = fopen("fseek.txt", "w");if (NULL == fp) {perror("open file fail");return 0;}//往fseek.txt文件写入this is test content 此时光标默认在末尾fputs("this is test content", fp);//移动光标到首部fseek(fp, 0, SEEK_SET);//写入seek到fseek.txt,此时文件内容是seek is test contentfputs("seek", fp);//移动光标到倒数第五个字节fseek(fp,-5,SEEK_END);//在倒数第五个字节的光标写入again,此时文件内容是seek is test coagainfputs("again", fp);//将光标移到开头//rewind(fp);//将光标移到末尾fseek(fp, 0, SEEK_END);    //计算末尾到开头的字节数int byte_size=ftell(fp);printf("byte_size=%d",byte_size);int count = ftell(fp);system("pause");return 0;}

程序运行结果

17e33e5055da33ded47e9d33efa967a3.png

获取文件信息

C语言提供了stat(const char *path, struct stat *buf)函数用于获取文件信息,如果获取成功返回0,获取失败则返回-1。stat()函数可以判断该文件存不存在获取文件状态。

在使用该函数前需要包含两个系统路径下的头文件:sys/types.h和sys/stat.h

#define _CRT_SECURE_NO_WARNINGS#include #include #include #include /*stat()函数获取文件状态@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){//定义stat结构体struct stat file_info;int info= stat("fwrite.txt",&file_info);//文件不存在if (info<0) {//打印输出提示信息printf("file not found ");}else {printf("获取文件信息: 文件大小是%d字节 ", file_info.st_size);}system("pause");return 0;}

程序运行结果

a144e0c671d6e4f87d63e3c0ae216b84.png

文件删除和重命名

文件删除

C语言提供了库函数remove(const char *path)来删除一个文件,参数需要一个文件的路径,删除成功返回0,删除失败返回-1

#define _CRT_SECURE_NO_WARNINGS#include #include /*文件删除@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){//删除当前路径下的fwrite.txt文件int flag=remove("fwrite.txt");if (flag==0) {printf("删除成功");}else {printf("删除失败");}system("pause");return 0;}

程序运行结果

394cfc7ae7769b9de9663b30112733ce.png

文件重命名

C语言提供了rename(const char *oldpath, const char *newpath)函数实现文件的重命名,该函数需要两个文件的完整路径

#define _CRT_SECURE_NO_WARNINGS#include #include /*rename()函数实现文件的重命名@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){//文件重命名rename("fseek.txt","fseek_rename.txt");system("pause");return 0;}

程序运行结果

ca81f879341c4c7a1ef4b5be7c9b7c62.png

Linux和Windows文本文件的区别

  • Windows字符串中带时存取的是
  • Linux中字符串带时存取的是
    如果把Windows的文本文件传到Linux系统上时使用编辑器打开会多了一个。而Linux的文本文件到Windows下就没有换行。

文件缓冲区

缓冲区本质就是内存中的一块临时空间,

当写入文件时,库函数会去调用内核提供的系统调用,例如fwrite()函数最终会调用write()系统调用。如果是大量频繁的写操作,会从用户空间切换到内核空间,上下文的切换会导致程序效率非常低。
因此引入了文件的缓冲区,当缓冲区满了才会一次性写入文件,或者有特殊场景可以调用fflush()强制刷新缓冲区,也就是将缓冲区的内容写入文件,或者程序正常退出(关闭Visual Studio的终端)时也会将缓冲区的文件写入磁盘文件。

#define _CRT_SECURE_NO_WARNINGS#include #include /*文件缓冲区@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){FILE* fp = fopen("data.txt","w");if (NULL==fp) {perror("open file fail");return -1;}//当不关闭终端时data.txt文件没有内容fputs("this is test content ",fp);system("pause");return 0;}
d3c794f1f56eb1697932a510afc0e2c1.png

缓冲区

刷新缓冲区的两种编码实现

#define _CRT_SECURE_NO_WARNINGS#include #include #include /*文件缓冲区@author liuguanglei 18601767221@163.com@wechat 18601767221@website ittimeline.net@version 2020/11/29*/int main(int argc, char* argv[]){FILE* fp = fopen("data.txt","w");if (NULL==fp) {perror("open file fail");return -1;}//当不关闭终端时data.txt文件没有内容fputs("this is test content ",fp);//可以调用fflush()函数实现强制刷新缓冲区的内容到data.txt;fflush(fp);//也可以将缓冲区写满char buf[1024] = "";//写入1M的1for (int i = 0; i < 1024;i++) {memset(buf, '1', sizeof(buf));fwrite(buf, 1, sizeof(buf), fp);}system("pause");return 0;}

而Windows下的stdout 是没有缓冲区的,即使用printf()函数打印数据到终端时不会进入缓冲区,直接写入到终端上。而Linux下的stdout文件是有缓冲区的。
Windows下标准输入(stdin) 不能调用fflush()强制刷新。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/561120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎样配置mysql数据源_mysql怎样配置ODBC数据源

选中 sqlserver选择默认连接的数据库 7、配置完成&#xff0c;可以测试连接 扩展资料&#xff1a; spring中配置数据源的几种常见方式&#xff1a;工具/原料 事先配置相应的环境mysql(mysql安装程序)mysql-connector-odbc-3.51.20-win32.exe(mysql数据源dobc安装程序) 步骤/方法…

python字符串用法_笔记:python字符串的使用

Python 没有表示单个字符的字符类型&#xff0c;只有字符串类型str。字符串是用单引号或双引号括起来的一系列字符。单引号表示的字符串中可以包含双引号字符&#xff0c;但不能直接包含单引号字符(否则无法知道字符串的开始和结尾分别在哪里)。同样&#xff0c;双引号表示的字…

new出来的对象怎么回收_JVM的内存模型及垃圾回收算法

1、什么是jvm&#xff1a;虚拟出来的计算机&#xff0c;是jre的一部分&#xff0c;使用jvm是为了支持与操作系统无关&#xff0c;实现跨平台&#xff0c;jvm内部体系结构主要分为三个部分&#xff1a;类加载器子系统&#xff0c;运行时数据区和执行引擎。2、jvm内存区域运行时数…

条令考试小程序辅助器_可以自己编题的答题软件,自定义题库考试出题工具,微信答题小程序...

自制题库自己编题的答题小程序要如何制作&#xff1f;今天给大家介绍下可以自己编题的答题软件&#xff0c;自制题库软件在微信小程序里自己出题&#xff0c;然后给别人来答题。每个人都可以通过这个小程序系统出考题&#xff0c;然后给到别人答题&#xff08;自己、同事、学生…

编写有效用例电子版_软件测试人员必须编写代码吗?

相信每一个刚入门软件测试的小伙伴都会琢磨一个问题&#xff1a;软件测试人员&#xff0c;要不要写代码&#xff1f;其实这个问题同样困扰着已经在测试行业闯荡了几年的测试小司机们。那今天&#xff0c;我就来给大家分析一下~01各种软件测试角色一般而言软件测试大体可以分为两…

bert 中文 代码 谷歌_ELECTRA中文预训练模型开源,110个参数,性能媲美BERT

感谢参考原文-http://bjbsair.com/2020-03-27/tech-info/7050/ 在去年11月份&#xff0c;NLP大神Manning联合谷歌做的ELECTRA一经发布&#xff0c;迅速火爆整个NLP圈&#xff0c;其中ELECTRA-small模型参数量仅为 BERT-base模型的1/10&#xff0c;性能却依然能与BERT、RoBERTa等…

监督学习和无监督学习_机器学习的要素是什么? 有监督学习和无监督学习两大类...

如前所述&#xff0c;机器学习是AI的一个子集&#xff0c;通常分为两大类&#xff1a;有监督学习和无监督学习。监督学习教学AI系统的常用技术是通过使用大量带标签的示例来训练它们。这些机器学习系统被馈入大量数据&#xff0c;这些数据已被注释以突出显示感兴趣的功能。这些…

如何用python计算levenshteindistance_Levenshtein计算相似度距离

使用Levenshtein计算相似度距离&#xff0c;装下模块&#xff0c;调用下函数就好。拿idf还得自己去算权重&#xff0c;而且不一定准确度高&#xff0c;一般做idf还得做词性归一化&#xff0c;把动词形容词什么全部转成名词&#xff0c;很麻烦。Levenshtein.distance(str1,str2)…

欧姆龙变频器MX2参数_第442期丨【源程序】基于三菱西门子欧姆龙松下PLC实现喷水池控制系统;欧姆龙PLC编程软件更新步骤...

论坛周刊1 Dec 2019本期论坛周刊精彩内容&#xff1a;1、【源程序】基于三菱\西门子\欧姆龙\松下PLC实现喷水池控制系统2、欧姆龙PLC编程软件更新步骤3、RSLinx Classic EntherNet/IP配置4、这个运动控制算厉害么5、施耐德、ABB、西门子接连登门拜访往期精选▼第441期丨施耐德电…

linux两台服务器 同一个地址_【网工玩Linux】搭建开源多运营商(ISP)链路负载均衡器...

今天&#xff0c;主要想讲一下如何利用Linux内核功能&#xff0c;搭建与市面上十几万的商用产品&#xff08;F5、RADWARE等&#xff09;功能相同的多互联网线路负载均衡设备。负载均衡&#xff0c;相信各位是了解的。主要包括两大类&#xff0c;一类是应用负载均衡&#xff0c;…

python拦截修改数据包_会Python?那么你一定要试一试mitmproxy

mitmproxy 是一款工具&#xff0c;也可以说是 python 的一个包&#xff0c;使用这个工具可以在命令行上进行抓包(现在也可以在web页面上查看上抓的数据包了)&#xff0c;还可以对所抓到的包进行脚本处理&#xff0c;非常有用。和 fiddler 或charles 等接口抓包工具相比&#xf…

java sha1_java使用SHA1加密算法详解

java使用SHA1加密算法程序源码&#xff1a;//下面四个import放在类名前面 包名后面import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Arrays;public static String getSha1(S…

小程序 wxml selectable_微信小程序 抽象节点

抽象节点这个特性自小程序基础库版本 1.9.6 开始支持。在组件中使用抽象节点有时&#xff0c;自定义组件模板中的一些节点&#xff0c;其对应的自定义组件不是由自定义组件本身确定的&#xff0c;而是自定义组件的调用者确定的。这时可以把这个节点声明为“抽象节点”。例如&am…

queue double java_一文弄懂java中的Queue家族

java中Queue家族简介简介java中Collection集合有三大家族List&#xff0c;Set和Queue。当然Map也算是一种集合类&#xff0c;但Map并不继承Collection接口。List&#xff0c;Set在我们的工作中会经常使用&#xff0c;通常用来存储结果数据&#xff0c;而Queue由于它的特殊性&am…

semantic ui中文文档_Vuetify-广受欢迎的Material风格的开源UI框架

全世界范围内广受欢迎的 Vue UI 框架&#xff0c;一个非常精致的 Material Design UI 套件。 Material Design 风格 UI 框架Vuetify 是一个基于 Vue.js 精心打造 UI 组件库&#xff0c;整套 UI 设计为 Material 风格。能够让没有任何设计技能的开发者创造出时尚的 Material 风格…

提示tun虚拟网卡没有安装_Win10家庭版通过Hyper-V安装Centos7+Python3.7过程总结

Win10专业版自带有虚拟机Hyper-V, 只需要在控制面板--程序中将其添加到应用就可使用&#xff0c;非常方便&#xff0c;但我电脑预装的是Win10家庭版&#xff0c;没有这个工具&#xff0c;但可以通过以下方法把它安装上&#xff1a;新建文件Hyper-V.cmd&#xff0c;文件内容&…

nginx 带宽_谈谈Nginx和LVS各自的优缺点以及使用

在最开始呢&#xff0c;咱们先说一下什么叫负载均衡&#xff0c;负载均衡呢&#xff0c;就是将一批请求&#xff0c;根据请求的内容&#xff0c;分发到不同的后端去进行相应的处理&#xff0c;从而提供负载分担&#xff0c;主备切换等功能。对于不同的负载均衡软件&#xff0c;…

wordpress 自定义分类url 重写_WordPress导航主题-WebStack导航主题

8月份写了一个导航主题&#xff0c;陆陆续续更新了十几版&#xff0c;功能自认已经很完善了&#xff0c;知乎也注册很久了&#xff0c;在这水片文章。首页截图预览地址一为忆 - 收集国内外优秀设计网站、UI设计资源网站、灵感创意网站、素材资源网站&#xff0c;定时更新分享优…

sql跨表查询_白话django之ORM的查询语句

教程源码&#xff1a;z991/django_turital在日常开发中&#xff0c;数据库的增删改查&#xff08;CDUR&#xff09;中&#xff0c;查询需求偏多&#xff0c;所以查询的语法比增删改操作多得多&#xff0c;尤其是跨表关联查询&#xff0c;可以让代码精简很多年。直接上代码吧&am…

看不懂论文代码怎么办_学位论文中的公式排版(制表位+mathtype+域)

写在前面为什么把公式排版单独拉出来写一篇文章呢&#xff1f;因为公式排版实在是太难了。公式居中标号右对齐&#xff0c;简直反人类好么。在学校期间一直寻找方便的公式排版自动编号方法&#xff0c;但搜索出来的大多只是用到了制表位&#xff0c;公式标号还要自己敲。最后毕…