【C语言】文件操作全解速览

文件操作目录

文件操作

文件分为二进制文件和文本文件,文本文件里面保存的内容形式是ASCII字符,二进制文件里面内容保存形式是01表示的。文件的主要作用是用来进行数据的持久化,能去长久的保存数据。这里f开头的文件操作命令,大多是c标准库里面的文件操作命令。

每个进程的PCB里面都有一份文件描述符表,文件描述符就是这个表的索引,通过索引可以获取这个文件描述符表中的内容,这个内容就是指向打开文件的FILE结构体指针。不同操作系统定义的FILE结构体不太一样,这里我拿出我的这一种作为参考。

c 复制代码
struct _IO_FILE {
  int _flags;		/* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags

  /* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;	/* Current read pointer */
  char* _IO_read_end;	/* End of get area. */
  char* _IO_read_base;	/* Start of putback+get area. */
  char* _IO_write_base;	/* Start of put area. */
  char* _IO_write_ptr;	/* Current put pointer. */
  char* _IO_write_end;	/* End of put area. */
  char* _IO_buf_base;	/* Start of reserve area. */
  char* _IO_buf_end;	/* End of reserve area. */
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */

  struct _IO_marker *_markers;

  struct _IO_FILE *_chain;

  int _fileno;		//文件描述符
};
typedef struct _IO_FILE FILE;

1. 文件的打开和关闭

要对文件操作,首先要打开文件,打开文件使用fopen函数,返回的是一个FILE类型指针。这个FILE指针指向的是一个文件节点,里面有文件操作的基本信息。

fopen()/fclose()

文件的打开和关闭

c 复制代码
#include <stdio.h>
//filepath 文件路径,mode打开模式
FILE * fopen(const char * filepath, const char * mode);

#include <stdio.h>
//关闭文件
int fclose(FILE * fp);


//mode ,其中b是二进制文件
//r或rb只读模式
//w或wb写模式(文件有内容就清空),文件不存在就新建
//a或ab追加模式,在文件末尾添加内容,文件不存在就创建
//r+或者rb+以可读可写方式打开文件
//w+或者wb+以可读可写方式打开文件,没有就新建
//a+或者ab+以追加可读可写方式打开文件,没有就创建

//案例
FILE *file = fopen("hello.txt", "w+");
if(file==NULL)
{
    perror("open");
    return -1;
}
fclose(file);

2. 文件读写位置相关

EOF表示文本文件结束符,在读取文件时作为读取文件结束标志。

c 复制代码
#define EOF (-1)

feof()

判断是否读取到了文件结尾

c 复制代码
#include <stdio.h>
int feof(FILE * stream);
//返回 
//非0:已经到文件结尾
//0:没有到文件尾

ftell()

获取文件流的读写位置

c 复制代码
#include <stdio.h>
long ftell(FILE *stream);

fseek()

移动文件的读写位置

c 复制代码
#include <stdio.h>
//fp是打开的文件指针
//offset是偏移量,正数是基于whence向后偏移,负数是基于whence向前偏移
//whence选取:
//SEEK_SET:文件开头
//SEEK_CUR:当前位置
//SEEK_END:文件末尾
int fseek(FILE *fp, long offset, int whence);


//案例 利用函数获取文件大小
fseek(fp,0,SEEK_END);
int len=ftell(fp);
printf("size is %d\n",len);

rewind()

把文件流的读写位置移动到文件开头

c 复制代码
#include <stdio.h>
void rewind(FILE *stream);

3. 文件内容读取

fgetc()/fputc()

按照字符读取文件

c 复制代码
#include <stdio.h>
//获取 fp 中的字符数据
int fgetc(FILE *fp);
//将ch转换为unsigned char后写入 fp 指定的文件中
int fputc(int ch, FILE * fp);


//案例 拷贝一个文件
FILE *file = fopen("hello.txt", "a+");
FILE *new = fopen("new.txt", "a+");
char ch;
while(!feof(file))
{
    ch = fgetc(file);
    fputc(ch,new);
    printf("%c",ch);
}
fclose(file);
fclose(new);

fgets()/fputs()

按照行读取文件

c 复制代码
#include <stdio.h>
//从 filepath 读入字符,保存到str,直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止,最后会自动加上字符 '\0' 作为字符串结束。
char * fgets(char * str, int size, FILE * filepath);
//将str写入 filepath 中,字符串结束符 '\0'  不写入文件
int fputs(const char * str, FILE * filepath);

//案例 拷贝一个文件
FILE *file = fopen("hello.txt", "r+");
FILE *new = fopen("new.txt", "w+");
char buf[100] = {0};

while (!feof(file))
{
	memset(buf, 0, sizeof(buf));
	char *p = fgets(buf, sizeof(buf), file);
	if (p != NULL)
	{
        fputs(buf,new);
		printf("%s", buf);
	}
}
fclose(file);
fclose(new);

fprintf()/fscanf()

按照格式读写文件。

c 复制代码
#include <stdio.h>
//根据 format字符串格式化数据,然后将结果输出到 filepath 文件中,指定出现字符串结束符 '\0'为止。
int fprintf(FILE * filepath, const char * format, ...);
//从 filepath 读取字符串,并根据format字符串来格式化数据。
int fscanf(FILE * filepath, const char * format, ...);

//案例 拷贝一个文件,并且修改内容格式
FILE *file = fopen("hello.txt", "r+");
FILE *new = fopen("new.txt", "w+");
char buf[100] = {0};
while (!feof(file))
{
    memset(buf, 0, sizeof(buf));
    int len=fscanf(file, "%s",buf);
    if(len>0)
    {
        fprintf(new,"name is %s\n",buf);
        printf("%s\n",buf);
    }
}
fclose(file);
fclose(new);

fread()/fwrite()

以数据块的方式读写文件

c 复制代码
#include <stdio.h>
//将 filepath 的内容拷贝到 ptr 缓冲区中,如果缓冲区是char数组,那么size为1,nmemb为数组长度
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *filepath);
//将 ptr 缓冲区的内容拷贝到 filepath 中,如果缓冲区是char数组,那么size为1,nmemb为数组的内容长度
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *filepath);

//案例  拷贝一张图片
FILE * bili = fopen("bilibili.png","rb");
FILE * cop = fopen("copy.png","wb");

char buf[1024]={0};
long sum=0;
while(!feof(bili))
{	
    memset(buf,0,sizeof(buf));
    int ret = fread(buf,1,sizeof(buf),bili);
    printf("read size is:%d\n",ret);
    sum+=ret;
    long pos=ftell(bili);
    printf("pos is:%ld,  sum is:%ld\n",pos,sum);
    fwrite(buf,1,ret,cop);
}
fclose(bili);
fclose(cop);

fflush()

读写缓冲器更新,常用于文件读写到缓冲区后立即输出到文件中,而不是等程序结束去刷新。

c 复制代码
#include <stdio.h>
//更新缓冲区数据到文件中保存,避免断电丢失
int fflush(FILE *stream);

4. 其他

stat()/fstat()

获取文件状态信息

c 复制代码
#include <sys/types.h>
#include <sys/stat.h>
//filepath 文件路径
//buf 保存文件信息的结构体
int stat(const char *filepath, struct stat *buf);
//fd 是文件描述符
int fstat(int fd, struct stat *statbuf);
 
//stat结构体定义
struct stat {
    dev_t     st_dev;         /* ID of device containing file */
    ino_t     st_ino;         /* Inode number */
    mode_t    st_mode;        /* File type and mode */
    nlink_t   st_nlink;       /* Number of hard links */
    uid_t     st_uid;         /* User ID of owner */
    gid_t     st_gid;         /* Group ID of owner */
    dev_t     st_rdev;        /* Device ID (if special file) */
    off_t     st_size;        /* 总大小Total size, in bytes */
    blksize_t st_blksize;     /* 文件块大小 Block size for filesystem I/O */
    blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */

    /* Since Linux 2.6, the kernel supports nanosecond
       precision for the following timestamp fields.
       For the details before Linux 2.6, see NOTES. */

    struct timespec st_atim;  /* Time of last access */
    struct timespec st_mtim;  /* Time of last modification */
    struct timespec st_ctim;  /* Time of last status change */

#define st_atime st_atim.tv_sec      /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};


//案例 使用 fstat 输出文件属性
FILE * file = fopen("test.txt","r");
struct stat fileStat;

fstat(file->_fileno,&fileStat);

printf("%ld\n",fileStat.st_size);

fclose(file);

remove()

删除文件

c 复制代码
#include <stdio.h>
int remove(const char *pathname);

rename()

文件更名

c 复制代码
#include <stdio.h>
//oldpath 当前文件名 ;   newpath 新文件名 相对路径或者绝对路径
int rename(const char *oldpath, const char *newpath);

最后

推荐一个零声教育学习教程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:链接

相关推荐
Kisorge1 小时前
【C语言】指针数组、数组指针、函数指针、指针函数、函数指针数组、回调函数
c语言·开发语言
轻口味2 小时前
命名空间与模块化概述
开发语言·前端·javascript
晓纪同学3 小时前
QT-简单视觉框架代码
开发语言·qt
威桑3 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
飞飞-躺着更舒服3 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
明月看潮生3 小时前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生3 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans3 小时前
C# 中串口读取问题及解决方案
开发语言·c#
盛派网络小助手3 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
Chinese Red Guest4 小时前
python
开发语言·python·pygame