满城区城乡建设局网站,百度竞价推广代运营话术,网站建设总结与,电脑视频制作软件欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab#xff0c;机器人运动控制、多机器人协作#xff0c;智能优化算法#xff0c;滤波估计、多传感器信息融合#xff0c;机器学习#xff0c;人工智能等相关领域的知识和… 欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab机器人运动控制、多机器人协作智能优化算法滤波估计、多传感器信息融合机器学习人工智能等相关领域的知识和技术。 C语言文件操作 | 文件分类、文件打开与关闭、文件的读写、文件状态、文件删除与重命名、文件缓冲区 文件的分类磁盘文件的分类文本文件和二进制文件 文件的打开和关闭文件指针文件的打开文件的关闭 文件的顺序读写按照字符读写文件fgetc、fputc按照行读写文件fgets、fputs按照格式化文件fprintf、fscanf按照块读写文件fread、fwrite 文件的随机读写Windows和Linux文本文件区别获取文件状态删除文件、重命名文件名文件缓冲区文件缓冲区磁盘文件的存取更新缓冲区 专栏《精通C语言》 文件的分类
磁盘文件和设备文件 磁盘文件 指一组相关数据的有序集合,通常存储在外部介质(如磁盘)上使用时才调入内存。 设备文件 在操作系统中把每一个与主机相连的输入、输出设备看作是一个文件把它们的输入、输出等同于对磁盘文件的读和写。
磁盘文件的分类
计算机的存储在物理上是二进制的所以物理上所有的磁盘文件本质上都是一样的以字节为单位进行顺序存储。
从用户或者操作系统使用的角度逻辑上把文件分为
文本文件基于字符编码的文件二进制文件基于值编码的文件
文本文件和二进制文件
文本文件
基于字符编码常见编码有ASCII、UNICODE等一般可以使用文本编辑器直接打开数5678的以ASCII存储形式(ASCII码)为 00110101 00110110 00110111 00111000
二进制文件
基于值编码,自己根据具体应用,指定某个值是什么意思把内存中的数据按其在内存中的存储形式原样输出到磁盘上数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函数默认输出信息到此终端。
文件的打开
任何文件使用之前必须打开
#include stdio.h
FILE * fopen(const char * filename, const char * mode);
功能打开文件
参数filename需要打开的文件名根据需要加上路径mode打开文件的模式设置
返回值成功文件指针失败NULL第一个参数的几种形式: 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);第二个参数的几种形式(打开文件的方式)
打开模式含义r或rb以只读方式打开一个文本文件不创建文件若文件不存在则报错w或wb以写方式打开文件(如果文件存在则清空文件文件不存在则创建一个文件)a或ab以追加方式打开文件在末尾添加内容若文件不存在则创建文件r或rb以可读、可写的方式打开文件(不创建新文件)r或rb以可读、可写的方式打开文件(不创建新文件)w或wb以可读、可写的方式打开文件(如果文件存在则清空文件文件不存在则创建一个文件)a或ab以添加方式打开文件打开文件并在末尾更改文件,若文件不存在则创建文件
注意
b是二进制模式的意思b只是在Windows有效在Linux用r和rb的结果是一样的。Unix和Linux下所有的文本文件行都是\n结尾而Windows所有的文本文件行都是\r\n结尾。在Windows平台下以“文本”方式打开文件不加b 当读取文件的时候系统会将所有的 “\r\n” 转换成 “\n” 当写入文件的时候系统会将 “\n” 转换成 “\r\n” 写入 以二进制方式打开文件则读\写都不会进行这样的转换。在Unix/Linux平台下“文本”与“二进制”模式没有区别“\r\n” 作为两个字符原样输入输出。
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;
}文件的关闭
任何文件在使用后应该关闭
打开的文件会占用内存资源如果总是打开不关闭会消耗很多内存。一个进程同时打开的文件数是有限制的超过最大同时打开文件数再次调用fopen打开文件会失败。如果没有明确的调用fclose关闭打开的文件那么程序在退出的时候操作系统会统一关闭。
#include stdio.h
int fclose(FILE * stream);
功能关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中并释放系统所提供的文件资源。
参数stream文件指针
返回值成功0失败-1FILE * fp NULL;fp fopen(abc.txt, r);fclose(fp);文件的顺序读写
按照字符读写文件fgetc、fputc
写文件
#include stdio.h
int fputc(int ch, FILE * stream);
功能将ch转换为unsigned char后写入stream指定的文件中
参数ch需要写入文件的字符stream文件指针
返回值成功成功写入文件的字符失败返回-1char buf[] this is a test for fputc;
int i 0;
int n strlen(buf);
for (i 0; i n; i)
{//往文件fp写入字符buf[i]int ch fputc(buf[i], fp);printf(ch %c\n, ch);
}文件结尾 在C语言中EOF表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志这种以EOF作为文件结束标志的文件必须是文本文件。在文本文件中数据都是以字符的ASCII代码值的形式存放。我们知道ASCII代码值的范围是0~127不可能出现-1因此可以用EOF作为文件结束标志。
#define EOF (-1)当把数据以二进制形式存放到文件中时就会有-1值的出现因此不能采用EOF作为二进制文件的结束标志。为解决这一个问题ANSI C提供一个feof函数用来判断文件是否结束。feof函数既可用以判断二进制文件又可用以判断文本文件。
#include stdio.h
int feof(FILE * stream);
功能检测是否读取到了文件结尾。判断的是最后一次“读操作的内容”不是当前位置内容(上一个内容)。
参数stream文件指针
返回值非0值已经到文件结尾0没有到文件结尾读文件
#include stdio.h
int fgetc(FILE * stream);
功能从stream指定的文件中读取一个字符
参数stream文件指针
返回值成功返回读取到的字符失败-1char ch;
#if 0
while ((ch fgetc(fp)) ! EOF)
{printf(%c, ch);
}
printf(\n);
#endifwhile (!feof(fp)) //文件没有结束则执行循环
{ch fgetc(fp);printf(%c, ch);
}
printf(\n);按照行读写文件fgets、fputs
写文件
#include stdio.h
int fputs(const char * str, FILE * stream);
功能将str所指定的字符串写入到stream指定的文件中字符串结束符 \0 不写入文件。
参数str字符串stream文件指针
返回值成功0失败-1char *buf[] { 123456\n, bbbbbbbbbb\n, ccccccccccc\n };
int i 0;
int n 3;
for (i 0; i n; i)
{int len fputs(buf[i], fp);printf(len %d\n, len);
}读文件
#include stdio.h
char * fgets(char * str, int size, FILE * stream);
功能从stream指定的文件内读入字符保存到str所指定的内存空间直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止最后会自动加上字符 \0 作为字符串结束。
参数str字符串size指定最大读取字符串的长度size - 1stream文件指针
返回值成功成功读取的字符串读到文件尾或出错 NULLchar buf[100] 0;while (!feof(fp)) //文件没有结束
{memset(buf, 0, sizeof(buf));char *p fgets(buf, sizeof(buf), fp);if (p ! NULL){printf(buf %s, buf);}
}按照格式化文件fprintf、fscanf
写文件
#include stdio.h
int fprintf(FILE * stream, const char * format, ...);
功能根据参数format字符串来转换并格式化数据然后将结果输出到stream指定的文件中指定出现字符串结束符 \0 为止。
参数stream已经打开的文件format字符串格式用法和printf()一样
返回值成功实际写入文件的字符个数失败-1fprintf(fp, %d %d %d\n, 1, 2, 3);读文件
#include stdio.h
int fscanf(FILE * stream, const char * format, ...);
功能从stream指定的文件读取字符串并根据参数format字符串来转换并格式化数据。
参数stream已经打开的文件format字符串格式用法和scanf()一样
返回值成功参数数目成功转换的值的个数失败 - 1int a 0;
int b 0;
int c 0;
fscanf(fp, %d %d %d\n, a, b, c);
printf(a %d, b %d, c %d\n, a, b, c);按照块读写文件fread、fwrite
写文件
#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 * nmembstream已经打开的文件指针
返回值成功实际成功写入文件数据的块数目此值和nmemb相等失败0typedef 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);读文件
#include stdio.h
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能以数据块的方式从文件中读取内容
参数ptr存放读取出来数据的内存空间size size_t 为 unsigned int类型此参数指定读取文件内容的块数据大小nmemb读取文件的块数读取文件数据总大小为size * nmembstream已经打开的文件指针
返回值成功实际成功读取到内容的块数如果此值比nmemb小但大于0说明读到文件的结尾。失败0typedef 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);
}文件的随机读写
#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#include stdio.h
long ftell(FILE *stream);
功能获取文件流文件光标的读写位置。
参数stream已经打开的文件指针
返回值成功当前文件流文件光标的读写位置失败-1#include stdio.h
void rewind(FILE *stream);
功能把文件流文件光标的读写位置移动到文件开头。
参数stream已经打开的文件指针
返回值无返回值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);
}
Windows和Linux文本文件区别
b是二进制模式的意思b只是在Windows有效在Linux用r和rb的结果是一样的。Unix和Linux下所有的文本文件行都是\n结尾而Windows所有的文本文件行都是\r\n结尾。在Windows平台下以“文本”方式打开文件不加b 当读取文件的时候系统会将所有的 “\r\n” 转换成 “\n” 当写入文件的时候系统会将 “\n” 转换成 “\r\n” 写入 以二进制方式打开文件则读\写都不会进行这样的转换。在Unix/Linux平台下“文本”与“二进制”模式没有区别“\r\n” 作为两个字符原样输入输出。
判断文本文件是Linux格式还是Windows格式:
#includestdio.hint main(int argc, char **args)
{if (argc 2)return 0;FILE *p fopen(args[1], rb);if (!p)return 0;char a[1024] { 0 };fgets(a, sizeof(a), p);int len 0;while (a[len]){if (a[len] \n){if (a[len - 1] \r){printf(windows file\n);}else{printf(linux file\n);}}len;}fclose(p);return 0;
}获取文件状态
#include sys/types.h
#include sys/stat.h
int stat(const char *path, struct stat *buf);
功能获取文件状态信息
参数
path文件名
buf保存文件信息的结构体
返回值
成功0
失败-1struct stat {dev_t st_dev; //文件的设备编号ino_t st_ino; //节点mode_t st_mode; //文件的类型和存取的权限nlink_t st_nlink; //连到该文件的硬连接数目刚建立的文件值为1uid_t st_uid; //用户IDgid_t st_gid; //组IDdev_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.hint 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;
}删除文件、重命名文件名
#include stdio.h
int remove(const char *pathname);
功能删除文件
参数pathname文件名
返回值成功0失败-1#include stdio.h
int rename(const char *oldpath, const char *newpath);
功能把oldpath的文件名改为newpath
参数
oldpath旧文件名
newpath新文件名
返回值
成功0
失败 - 1文件缓冲区
文件缓冲区
ANSI C标准采用“缓冲文件系统”处理数据文件。
所谓缓冲文件系统是指系统自动地在内存区为程序中每一个正在使用的文件开辟一个文件缓冲区从内存向磁盘输出数据必须先送到内存中的缓冲区装满缓冲区后才一起送到磁盘去。
如果从磁盘向计算机读入数据则一次从磁盘文件将一批数据输入到内存缓冲区(充满缓冲区)然后再从缓冲区逐个地将数据送到程序数据区(给程序变量) 。
磁盘文件的存取 磁盘文件一般保存在硬盘、U盘等掉电不丢失的磁盘设备中在需要时调入内存。在内存中对文件进行编辑处理后保存到磁盘中。程序与磁盘之间交互不是立即完成系统或程序可根据需要设置缓冲区以提高存取效率。
更新缓冲区
#include stdio.h
int fflush(FILE *stream);
功能更新缓冲区让缓冲区的数据立马写到文件中。
参数
stream文件指针
返回值
成功0
失败-1