文件操作(打开--操作--关闭)

概述

  • 文件

    保存于外存储器上(磁盘、U盘、移动硬盘)的数据集合。

  • 文件操作
    1. 文件内容的读取、写入(视为对文件输入输出操作,像流一样,称为文件流);

    2. c语言采用“文件缓冲机制”,系统为文件创建“文件缓冲区”;

  • 文件的分类

    按存储方式划分:文本文件(ASCII文件)和 二进制文件

  • 文件标识
    1. 文件系统中:路径+文件名,举例:d:/aaa/bbb/ccc

    2. c语言程序中:文件指针,语法:FILE *指针变量名

  • 文件操作步骤
    1. 打开文件

    2. 文件处理(读写)

    3. 关闭文件

文件的操作

打开

让系统为文件创建文件缓冲区

  • 函数名:fopen

  • 头文件:#include

  • 函数原型:FILE* fopen(const char *path,const char *mode);返回值类型 函数名 参数

  • 函数功能:打开文件,为文件创建缓冲区

  • 函数参数:

    1. path:目标文件路径

    2. mode:文件打开方式(读、写、读写)

  • 返回值:

    • 成功:返回文件指针File*(缓冲区首地址)

    • 失败:返回NULL

关闭

文件使用完毕,一定要释放

  • 函数名:fclose

  • 头文件:#include

  • 函数原型:int fclose(FILE* fp)

  • 函数功能:关闭文件,释放缓冲区

  • 函数参数:

    • fp:已经打开的文件指针

  • 返回值:

    • 成功:返回0

    • 失败:返回EOF(-1)

  • 文件打开关闭案例:

#include 

int main(int argc, char** argv)
{
    //在命令行执行可执行文件时,传递一个需要打开的目标文件地址,进行参数判断
    if(argc < 2)
    {
        printf("输入有误,请按照 <%s 文件路径> 格式输入\n", argv[0]);   
        return -1;
    }
    
    //根据文件路径,打开文件,mode(r,w,rw)
    FILE* fp = fopen(argv[1],"r");
    
    //检验文件是否打开成功
    if(!fp)
    {
        perror("文件打开失败!");    
        return -1;
    }
    puts("文件打开成功!\n");
    
    // 关闭打开的文件
    int ret = fclose(fp);
    // 校验文件是否关闭成功(很多时候这一步会省略掉)
    /*
    if(ret == -1)
    {
        perror("文件关闭失败!");
        
        return -1;
    }
    puts("文件关闭成功!");
    */
    return 0;
}
顺序读写
  • 读取文件
    • 单字符读取

      • 函数名:fgetc

      • 头文件:#include

      • 函数原型:int fgetc(File* fp);

      • 函数功能:从fp代表文件中获取一个字符

      • 函数参数:

        1. fp:我们需要操作的文件

      • 返回值:

        1. 成功:返回读取到的字符

        2. 失败:或文件末尾,返回EOF(-1)

    单字符读取案例:

#include 

int main(int argc, char ** argv)
{
    if(argc < 2)
    {
        printf("输入有误,请按照 <%s 文件路径> 格式输入\n", argv[0]);
        return -1;
    }
    
    
    FILE* fp = fopen(argv[1],"r");
    
    if(!fp)
    {
        perror("文件打开失败!");
        return -1;
    }
    
    int re = 0;
    
    while(re != -1 && re != '\n')
    {
        re = fgetc(fp);
        printf("%c", re);
    }
    //方式二
    /*
    char ch;
    
    while( (ch = fgetc(fp)) != EOF)
    {
    	printf("%c", ch);
    }
    */
    printf("\n");
    
    fclose(fp);
    
    return 0;
}
  • 多字符读取

    • 函数名:fgets

    • 头文件:#include

    • 函数原型:char *fgets(char *buf, int size, FILE *fp);

    • 函数功能:从fp代表文件获取size个字符,放置到buf代表内存中

    • 函数参数:

      • buf:内存空间首地址用于存放读取的字节

      • size:待读取的字符,实际读取size-1

      • fp:已经打开的文件指针

    • 返回值:

      • 成功:返回buf

      • 失败:文件末尾,返回NULL

多字符读取案例:

#include 
#include 

int main(int argc, char** argv)
{
    if(argc < 2)
    {
        printf("输入有误,请按 <%s 文件路径> 格式输入\n", argv[0]);
    	return -1;
    }
    
    FILE* fp = fopen(argv[1], "rw");
    
    if(!fp)
    {
        perror("文件打开失败!");
        return -1;
    }
    
    //创建缓冲区
    char buf[64] = {0};
    
    while(fgets(buf,64,fp) != NULL)
    {
        printf("%s",buf);
        //给缓冲区清空
        memset(buf,0,sizeof(buf));
    }
    printf("\n");
    
    fclose(fp);
    
    return 0;
}
写入文件

单字符写入

  • 函数名:fputc

  • 头文件:#include

  • 函数原型:int fputc(int c,File* fp);

  • 函数功能:向fp代表文件中写入一个字符c

  • 函数参数:

    1. c:待写入字符

    2. fp:已经打开的文件

  • 返回值:

    1. 成功:返回读取到的字符

    2. 失败:或文件末尾,返回EOF(-1)

单字符写入案例:

#include 

int main(int argc, char** argv)
{
    if(argc < 3)
    {
        printf("输入有误,请按 <%s 文件路径> 格式输入\n", argv[0]);
    	return -1;
    }
    
    FILE* fp = fopen(argv[1], "w");
    
    if(!fp)
    {
        perror("文件打开失败!");
        return -1;
    }
 
    //单个字符循环写入
    while(*argv[2] != '\0')
    {
        // ./a.out file1.txt I_LOVE_YOU
        fputc(*argv[2],fp);
        argv[2]++;
    }
    
    fclose(fp);
    return 0;
}
  • 多字符写入

    • 函数名:fputs

    • 头文件:#include

    • 函数原型:int fputs(const char *buf, FILE *fp);

    • 函数功能:向fp代表的文件中写入一个字符数组s

    • 函数参数:

      1. s:待写入的字符数组(写入缓冲区)

      2. fp:已打开的文件指针

    • 返回值:

      1. 成功:返回非负整数 (> 0)

      2. 失败:返回EOF(-1)

多字符写入案例:

#include 
 
int main(int argc,char **argv)
 {
    if(argc < 3)
    {
        printf("输入有误,请按照<%s 文件路径 文本数据>格式输入\n",argv[0]);
        return -1;
    }
 
    FILE* fp = fopen(argv[1],"w");
    
    if(!fp)
    {
        perror("文件打开失败!");
        return -1;
    }
   
    // ./a.out file1.txt I_Love_Your
    fputs(argv[2],fp);
 
    fclose(fp);
    
    return 0;
 }
  • 判文件结束
    • 函数名: feof(fp)

    • 头文件:#include

    • 函数原型:int feof(fp)

    • 函数功能:在读fp指向的文件时判断是否遇到文件结束。

    • 函数参数:

      1. fp:已打开的文件指针

    • 返回值:

      1. 文件未读取完毕:返回0

      2. 失败或文件读取完毕:返回非0

案例:

#include 
#include 
 
int main(int argc,char** argv)
 {
    
    if(argc < 3)
    {
        printf("输入有误,请按照<%s 源文件路径 目标文件路径>格式输入\n",argv[0]);
 
        return -1;
    }
    
    
    FILE* in = fopen(argv[1],"r");
    FILE* out = fopen(argv[2],"w");
 
    
    if(!in || !out)
    {
        perror("文件打开失败!");
        return -1;
    }
    // 单字符读写
    // while(!feof(in))
    // {
             // 读写操作
    //         fputc(fgetc(in),out);        
    //}
    
    
    char buf[64] = {0};
    
    // 使用循环读写文件
    while(fgets(buf,64,in)!=NULL)
    {
        // 写入数据
        fputs(buf,out);
        // 重置缓冲区
        memset(buf,0,sizeof(buf));        
    }
    
    printf("\n");
    // 关闭文件
    fclose(in);
    fclose(out);
 }
  • 数据块读写(二进制)
  • fread

    • 头文件:#include

    • 函数原型:size_t fread(void *ptr,size_t size,size_t count,FILE* fp)

    • 函数功能:从fp代表的文件中以size为单位(一个数据块)读取count个数据块存放在ptr内存 中。

    • 函数参数:

      1. ptr:内存空间首地址,用于存放读取到数据(缓冲区)

      2. size:数据块大小,以byte为单位

      3. count:待读取的数据块的个数

      4. fp:已打开的文件指针

    • 返回值:

      1. 成功:返回实际写入的字节数

      2. 失败:返回 < 0

    案例:

#include 
#define SIZE 4
 
// 创建学生结构体
struct Student
{
    char name[20];
    int num;
    int age;
    char addr[50];
} stud[SIZE];
 
void main()
{
    int i;
    FILE* fp;
 
    if((fp = fopen("stu-list","rb")) == NULL)
    {
        perror("文件打开失败!");
        return;
    }
    
    // 循环读取二进制文件
    for(i = 0; i < SIZE; i++)
    {
        fread(&stud[i],sizeof(struct Student),1,fp);
        // 将读到的内容输出到控制台
		printf("%-10s%4d%4d%-20s\n",stud[i].name,stud[i].num,stud[i].age,stud[i].addr);
    }
 
    fclose(fp);
 }

fwrite

  • 头文件:#include

  • 函数原型:size_t fwrite(const void* ptr,size_t size,size_t count,FILE* fp)

  • 函数功能:向fp代表的文件中以size为一个数据块,写入count个数据块到fp

  • 函数参数:

    1. ptr:内存空间首地址,用于存放待写入的数据,(写入缓冲区)

    2. size:数据块大小,以byte为单位

    3. count:待写入的数据块个数

    4. fp:已打开的文件指针

  • 返回值:

    1. 成功:返回实际写入字节数

    2. 失败:写入完毕,返回 < 0

案例:

从键盘输入4个学生的有关数据,然后把它们转存到磁盘文件上去

#include 
#define SIZE 4 // 学生数量

// 创建学生结构体
struct Student
{
	char name[20];
 	int num;
 	int age;
 	char addr[50];// 住址
} stud[SIZE];
 
// 保存学生信息到文件
void save()
{
 	FILE* fp;
 	int i;
    
     if((fp = fopen("stu-list","wb")) == NULL)// stu-list对应的目录:./stu-list,wb-二进制写
入,默认是文本写入
    {
        perror("文件打开失败!");
        return;
    }
 
    // 写入操作
    for(i = 0; i < SIZE; i++)
    {
        fwrite(&stud[i],sizeof(struct Student),1,fp);
    }
 
    // 关闭文件
    fclose(fp);
 
}
 
void main()
{
    int i;
  
    printf("请输入学生的信息:姓名,学号,年龄,住址\n");
  
    for(i = 0; i < SIZE;i++)
    {
        scanf("%s%d%d%s",stud[i].name,&stud[i].num,&stud[i].age,stud[i].addr);
        // 录入一个学生,就保存一个学生到文件中
        save();
    }
}
随机读写
  • 说明:读写文件内容时,可在指定的位置上读写数据

  • 文件随机读写的核心操作: 文件位置指针的定位

  • 文件位置指针的移动方法:

    • rewind

      • 头文件:#include

      • 函数原型: void rewind(FILE* fp);

      • 函数功能: 将文件位置指针定位到文件开头

      • 函数参数:

        1. fp: 已经打开的文件指针

      • 返回值: 无

    • fseek

      • 头文件: #include

      • 函数原型: int fseek(FILE *fp, long offset, int whence);

      • 函数功能: 将文件位置指针定位到指定位置

      • 函数参数:

        1. fp: 已经打开的文件指针

        2. offset: 相对于参考位置的偏移位置

        3. whence: 参考位置

          1. SEEK_SET 或 0 表示文件头

          2. SEEK_CUR 或 1 表示当前读写的位置

          3. SEEK_END 或 2 表示文件尾

      • 返回值:

        1. 成功 :0

        2. 失败 : -1

    • ftell

      • 头文件: #include

      • 函数原型: long ftell(FILE *fp);

      • 函数功能: 获取文件位置指针当前位置

      • 函数参数:

        1. fp: 已经打开的文件指针

      • 返回值:

        1. 成功 :文件位置指针当前位置

        2. 失败 : -1

    案例一:

有一个磁盘文件,第一次将它的内容显示在屏幕上,第二次把它复制到另一文件上
#include 
void main()
{
	FILE *fp1, *fp2;

 	fp1 = fopen("file1.c", "r");
 	fp2 = fopen("file2.c", "w");
 	while (!feof(fp1))
 		putchar(getc(fp1)); /*输出到屏幕*/
 	rewind(fp1);            /*位置指针返回到文件头*/
 	while (!feof(fp1))
 		putc(getc(fp1), fp2); /*从文件file1的头读起,输出到文件file2中*/
 	fclose(fp1);
 	fclose(fp2); /*关闭文件*/

案例二:

存有10个学生的数据。要求将第1、3、5、7、9个学生数据输入计算机,并在屏幕上显示出来
#include 
#include 
struct student_type
{
    char name[10];
    int num;
    int age;
    char sex;
} stud[10];
void main()
{
    int i;
    FILE *fp;
    if ((fp = fopen("stud-dat", "rb")) == NULL)
    {
        printf("can not open file\n");
        return;
    }
    for (i = 0; i < 10; i += 2)
    {
        fseek(fp, i * sizeof(struct student_type), 0);
        fread(&stud[i], sizeof(struct student_type), 1, fp);
        printf("%s %d %d %c\n", stud[i].name, stud[i].num, stud[i].age, stud[i].sex);
    }
    fclose(fp);
}

案例三:

用“追加”的形式打开文件gg.txt,查看文件读写指针的位置,然后向文件写入“data”,再查看文件读写指针的位置。

#include "stdio.h"
main()
{
    long p;
    FILE *fp;
    if ((fp = fopen("gg.txt","a")) == NULL)
    {
        printf("cannot open this file!\n");
        return;
    }
    p = ftell(fp);
 	printf("p=%ld\n",p);
    fputs("data", fp);
 	p = ftell(fp);
 	printf("p=%ld\n",p);
 	fclose(fp);
}

你可能感兴趣的:(c语言,开发语言)