首页 > 其他分享 >【C语言】文件操作全解速览

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

时间:2024-05-31 20:28:31浏览次数:32  
标签:文件 file int C语言 char FILE 速览 全解 buf

文件操作目录

文件操作

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

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

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()

文件的打开和关闭

#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表示文本文件结束符,在读取文件时作为读取文件结束标志。

#define EOF (-1)

feof()

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

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

ftell()

获取文件流的读写位置

#include <stdio.h>
long ftell(FILE *stream);

fseek()

移动文件的读写位置

#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()

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

#include <stdio.h>
void rewind(FILE *stream);

3. 文件内容读取

fgetc()/fputc()

按照字符读取文件

#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()

按照行读取文件

#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()

按照格式读写文件。

#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()

以数据块的方式读写文件

#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()

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

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

4. 其他

stat()/fstat()

获取文件状态信息

#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()

删除文件

#include <stdio.h>
int remove(const char *pathname);

rename()

文件更名

#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等技术内容,点击立即学习:链接

标签:文件,file,int,C语言,char,FILE,速览,全解,buf
From: https://blog.csdn.net/qq_44653106/article/details/139349686

相关文章

  • C语言相关介绍及编译器的使用教程
    文章目录C语言相关介绍及编译器的使用教程一、C语言是什么二、C语言的历史三、编译器的选择1.编译和链接2.VS2022使用步骤四、第一个C语言程序C语言相关介绍及编译器的使用教程一、C语言是什么二、C语言的历史三、编译器的选择及相关介绍和使用四、第一个C......
  • 初识C语言--第二天
       ---取地址符:&      & 叫做取地址符;&+变量名:可以获取变量在内存中的地址(通过%p可以打印在内存中的地址)示例:输出结果:(注:Linux64位操作系统环境下,打印出来的地址会很大,因为在64位操作系统中,地址变量在内存中占有8个字节)---C语言的输入函数scanf......
  • 【c语言】指针就该这么学(1)
    ......
  • 初识C语言第三十天——设计三子棋游戏
    目录一.设计游戏框架1.打印游戏菜单2.输入选择判断(玩游戏/游戏结束/输入错误重新输入)  二、玩游戏过程设计1.设计棋格存放棋子——二维数组2.初始化棋盘——初始化为空格3.打印棋盘——本质上就是打印数组4.游戏过程——1.玩家走棋2.判断结果 3.电脑走棋4.判断结......
  • C语言(字符函数和字符串函数)1
                          Hi~!这里是奋斗的小羊,很荣幸各位能阅读我的文章,诚请评论指点,关注+收藏,欢迎欢迎~~                           ......
  • 【C语言】动态内存管理
    前言为什么要有动态内存分配?可以回想一下目前为止,我们想要向内存申请一块空间存放数据,有哪些手段呢?目前我们遇到的方式主要有两种:一、创建一个变量。比如我们存放一个整型数据,就创建一个整型变量。(也就是申请4个字节)我们创建一个变量,存放了一个数据。intn=2077;二、如......
  • 【C语言】探索文件读写函数的全貌
    ......
  • C语言-字符输入/输出-20
    题目:那些一个通过命令运行的程序计算幂,第一个命令行参数是double类型的数,作为幂的底数,第二个参数是整数,作为幂的指数源代码:#include<stdio.h>#include<stdlib.h>intmain(intargc,char*argv[]){intnum;doublebase,base_total;while(argc<3......
  • C语言-字符输入/输出-19
    题目:编写一个程序,反序显示命令行的单词。源代码:#include<stdio.h>intmain(intargc,char*argv[]){for(inti=argc-1;i>0;i--){printf("%s",argv[i]);}return0;}演示效果:如果朋友你感觉文章的内容对你有帮助,可以点赞,关注文章和......
  • C语言练习题之——从简单到烧脑(11)(每日两道)
    题目1:有两个矩阵a[3][2],b[2][2],元素值由键盘输入,计算a与b的矩阵之和(两个矩阵循环中相加,结尾求和)#include<stdio.h>intmain(){ intarr[3][2],brr[2][2],i,j,sum1=0,sum2=0; for(i=0;i<3;i++) { for(j=0;j<2;j++) { scanf_s("%d",&arr[i][j]);......