C语言——文件

C语言目录:

1. 概述

2. 数据类型

3. 量

4. 运算符

5. 流程控制

6. 函数

7. C程序编译过程

8. 文件

9. 内存管理


文件流:C语言将文件看做一个字符序列,即文件是由若干字符组成的字符流

8.1 文件分类

8.1.1 文本文件

文件内容以ASCII码格式存放,一个字节存放一个ASCII码,代表一个字符 ,但占用存储空间较多

.c 文件就是以文本文件形式存放的

8.1.2 二进制文件

文件内容以补码格式存放,占用存储空间少。

数据按其内存中的存储形式原样存放

.exe 文件就是以二进制文件形式存放

8.1.3 示例

#include <stdio.h>

int main(){
    /*
     * 以文本形式存储
     * 会将每个字符先转换为对应的ASCII,
     * 然后再将ASCII码的二进制存储到计算机中
     */
    int num = 666;
    FILE *fa = fopen("ascii.txt", "w");
    fprintf(fa, "%d", num);
    fclose(fa);

    /*
     * 以二进制形式存储
     * 会将666的二进制直接存储到文件中
     */
    FILE *fb = fopen("bin.txt", "w");
    fwrite(&num, 4, 1, fb);
    fclose(fb);

    return 0;
}

在这里插入图片描述
在这里插入图片描述

  • 记事本默认按照ASCII码逐个解码文件,由于文本文件存储的是ASCII码,所以可以正常解析
  • 记事本按照ASCII码解码文件,所以解析出来是乱码

8.2 文件的操作

FILE 结构体

C语言中存放文件属性的结构体(缓冲区和文件读写状态),所有的文件操作都是通过 FILE 结构体完成的,只能通过指针访问属性

struct _iobuf {
    char *_ptr;  //文件输入的下一个位置
    int _cnt;  //当前缓冲区的相对位置
    char *_base; //文件的起始位置)
    int _flag; //文件标志
    int _file;  //文件的有效性验证
    int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取
    int _bufsiz; // 缓冲区大小
    char *_tmpfname; //临时文件名
};
typedef struct _iobuf FILE;

8.2.1 打开文件

建立程序和文件之间的通信通道,并为文件系统建立缓冲

所在文件:stdio.h

a. 参数及返回值
FILE *fopen(const char *filename,const char *mode);
//以mode的方式,打开filename命名的文件,返回一个指向该文件缓冲的FILE结构体指针
FILE *fp = fopen("路径","w");
参数/返回值含义
char *filename要打开或者创建文件的路径
mode打开文件的方式
FILE返回指向文件缓冲区的指针,用于操作文件
b. 文件读写方式
mode文件类型操作文件不存在文件存在
r文本文件读取出错打开文件
w文本文件写入创建新文件覆盖原文件
a文本文件追加创建新文件原文件后追加
r+文本文件读取/写入出错打开文件
w+文本文件读取/写入创建新文件覆盖原文件
a+文本文件读取/追加创建新文件原文件后追加
rb二进制文件读取出错打开文件
wb二进制文件写入创建新文件覆盖原文件
ab二进制文件追加创建新文件原文件后追加
rb+二进制文件读取/写入出错打开文件
wb+二进制文件读取/写入创建新文件覆盖原文件
ab+二进制文件读取/追加创建新文件原文件后追加

8.2.2 关闭文件

所在文件:stdio.h

函数功能:fclose() 用来关闭之前 fopen() 打开的文件

函数操作:让缓冲区内的数据写入文件,并释放系统提供的文件资源

a. 参数和返回值
int fclose(FILE *filePointer)
参数/返回值含义
FILE *filePointe指向文件缓冲的指针
int成功则返回0,失败则返回EOF(-1)
int main(){
	FILE *fp;
	if(fopen("abc.txt","w")==NULL){
        exit(-1);//非0表示异常
    }
    fclose(fp);
}

8.2.3 读写文件

需要引入 位置指针 :打开文件,默认指向文件开头

  • 所有文件读/写,都是从 位置指针 指示的位置进行读/写

分为

  • 顺序读写
  • 随机读写
a. 文本文件读写
文件尾测试函数

文件使用特殊字符 EOF 作为文件结束标记

int feof(FILE *stream); :判断是否读到文件结尾

  • 0表示未读到文件尾
  • 非0表示读到文件尾,此时不能读取文件

所在文件:stdio.h

参数:FILE *stream 是指向文件缓冲的指针

注意:文件只有读了才会修改 位置指针 ,没有打开并读取的文件无法通过 feof(fp) 判断是否读到文件尾,一定要 先读在判断

# include<stdio.h>

int main(){
    //打开文件
    FILE *fp = fopen("test.txt","r+");
    
    //从文件中读取内容
    char res = EOF;
    while(res = fgetc(fp) && !feof(fp)){
        printf("%c",res);
    }
    //关闭文件  
    fclose(fp);
    
    return 0;
}

在使用 feof() 判断文件尾时,最后一行没有 \n 会少读一行

#include <stdio.h>

int main(){
    FILE *fp = fopen("test.txt", "w+");

    fputs("asd\n", fp);
    fputs("123456", fp);
    rewind(fp);

    char str[1024];
    while(fgets(str, 1024, fp) && !feof(fp)){
        printf("str = %s", str); 
        //输出 str = asd
        //若最后一行加上 \n,则输出 
        //str = asd
        //str = 123456
    }
    
    fclose(fp);

    return 0;
}
读/写一个字符
读入一个字符输出一个字符所在文件
getchar()putchar()stdio.h
fgetc(fp)fputc(ch,fp)stdio.h

int fgetc(FILE *fp):从文件中读取一个字符,若到文件尾返回EOF

  • 正常情况返回一个int类型值
  • 读到文件尾或出错,返回 EOF
#include <stdio.h>

int main(){
    //打开文件
    FILE *fp = fopen("test.txt", "r+");

    //从文件中读取内容
    char res = EOF;
    while((res = fgetc(fp)) != EOF){
        printf("res = %c\n", res);
    }

    //关闭打开的文件
    fclose(fp);
    
    return 0;
}

int fputc(int ch,FILE *fp):将ch字符写入文件

  • 写入成功,返回写入的字符
  • 写入失败,返回 EOF
# include<stdio.h>

int main(){
   	//打开一个文件
    FILE *fp = fopen("test.txt","w+");
    
    //向文件中写入内容
    for(char ch = 'a';ch <= 'z';++ch){
       	char res = fputc(ch,fp);
        printf("%c",res);
    }
    
    //关闭打开的文件
    fclose(fp);
    
    return 0;
}
读/写一行字符串
读入字符串输出字符串所在文件
getchar()putchar()stdio.h
fgets(fp)fputs(s,fp)stdio.h

char *fgets(char *s,int n,FILE *fp) :从 fp 指向的文件中读取 n-1 个字符,写入s中;如果中间遇到 \0 或者 EOF ,读入结束,且在字符串最后添加 \0

  • 正常,返回 char *str 指针
  • 遇到 \nEOF则停止读取
  • 出错,返回空指针 NULL
#include <stdio.h>

int main(){
    
    FILE *fp = fopen("test.txt", "w+");

    fputs("asd\n", fp);
    fputs("123456\n", fp);
    rewind(fp);

    char str[1024];
    fgets(str, 1024, fp);//读到 \n 读取一行结束
    printf("str = %s", str); // asd

    fclose(fp);

    return 0;
}
#include <stdio.h>

int main(){
    FILE *fp = fopen("test.txt", "w+");
    
    fputs("asd\n", fp);
    fputs("123456", fp);
    rewind(fp);
    
    char str[1024];
    
    while(fgets(str, 1024, fp)){//读到文件尾,停止读
        printf("str = %s", str);//asd123456
    }
    fclose(fp);
    return 0;
}

int fputs(char *s,FILE *fp) :将 s 中的字符串写到 fp 指向的文件中

  • 正常则返回0
  • 出错则返回 EOF
# include<stdio.h>

int main(){
    FILE *fp = fopen("test.txt","w+");
    
    fputs("Hello ",fp);
    fputs("World!",fp);
    
    fclose(fp);
    
    return 0;
}

遇到 \0 自动终止写入

# include<stdio.h>

int main(){
    FILE *fp = fopen("test.txt","w+");
    fputs("asd\0asdasd\n",fp);
    
    fclose(fp);
    
    return 0;
}

在这里插入图片描述

格式读/写

int fscanf(FILE *fp,char *format)

读/写成功返回整数

int fprintf(FILE *fp,char *fprmat)

b. 二进制文件读/写

二进制文件的读写函数可以读取文本文件

文本文件的读写函数不可读取二进制文件

unsigned fread(void *ptr,unsigned size,unsigned n,FILE *fp)

从文件 fp 中读取 nsize 字节的数据块,存储于 ptr 指向的内存空间

  • 成功,则返回 n
  • 出错或文件结束,则返回0
#include <stdio.h>

int main(){
    // test.txt中存放的是"Hello\0 World!"
    FILE *fr = fopen("test.txt", "rb+");
    char buf[1024] = {0};
    
    int n = fread(buf, 1, 1024, fr);
    printf("%d\n", n);
    for(int i = 0; i < n; i++){
        printf("%c", buf[i]);
    }
    
    fclose(fr);
    
    return 0;
}

注意:读取时,size 取最小字节,n 可以随便写

  • 若读取时 size 不是最小字节,则会引起读取失败

    如存储的 char 类型 0A 1E 1C 2C 66 67 68

    size = 1 时,n=1024 ,会将文件中内容依次取出

    size = 4 时,n=1024 ,第一个数据块 0A 1E 1C 2C 会顺利取出,但最后剩下3个字节不足一个数据块,则最后一个块读取不到


unsigned fwrite(void *ptr,unsigned size,unsigned n,FILE *fp)

ptr 指向的存储空间的 nsize 字节的数据块写入文件 fp

  • 成功,则返回 n
  • 出错或文件结束,则返回0
# include<stdio.h>

int main(){
    FILE *fp = fopen("test.txt","wb+");
    char *str = "Hello\0 World!";
    
    fwrite((void *)str, 13 ,1, fp);
    
    fclose(fp);
    
    return 0;
}
读写数组
# include<stdio.h>

int main(){
    FILE *fp = fopen("test.txt","wb+");
   	int ages[4] = {1,3,5,7};
    fwrite(ages,sizeof(ages),1,fp);
    
    rewind(fp);
    
    int t;
    while(fread(&t,sizeof(int),1,fp) > 0){
        printf("data=%d\n",t);
    }
    fclose(fp);
    
    return 0;
}
读写结构体

结构体中的数据类型不统一,此时最适合用二进制的方式进行读写

单个结构体

# include<stdio.h>

typedef struct{
	char *name;
    int age;
    double height;
}Person;

int main(){
    Person p1 = {"A",23,1.7};
    FILE *fp = fopen("test.person","wb+");
    fwrite(&p1,sizeof(p1),1,fp);
    
    rewind(fp);
    Person p2;
    fread(&p2,sizeof(p2),1,fp);
    
    fclose(fp);
    
    return 0;
}

读写结构体数组

# include<stdio.h>

typedef struct{
	char *name;
    int age;
    double height;
}Person;

int main(){
    Person ps[] = {
        {"A", 18, 1.65},
      	{"B", 21, 1.88},
      	{"C", 33, 1.9}
    };
    
    FILE *fp = fopen("test.person","wb+");
    fwrite(&ps,sizeof(ps),1,fp);
    
    rewind(fp);
    Person p;
    while(fread(&p,sizeof(p),1,fp) > 0){
        printf("name = %s,age = %d,height = %lf\n"
               ,p.name,p.age,p.height);
    }
    
    fclose(fp);
    
    return 0;
}

8.2.4 文件操作函数

a. 获取文件位置指针

long ftell(FILE *fp) :返回距文件头的字节数

  • 成功,则返回整型
  • 失败,返回-1
#include <stdio.h>

int main(){
    char *str = "abcedfg";
    FILE *fp = fopen("test.txt", "w+");

    long p = ftell(fp);
    printf("p = %ld\n", cp); // 0
    
    // 写入一个字节
    fputc(str[0], fp);
    p = ftell(fp);
    printf("p = %ld\n", p); // 1
    
    fclose(fp);
    
    return 0;
}
b. 位置指针重定位

void rewind() :使位置指针指向文件头

c. 文件定位函数

int fseek(FILE *fp, long offset, int origin ); : 将位置指针移动到指定位置

  • fp :文件的指针,指向要操作的文件

  • offset :表示要移动的字节数

    offset 为正时,向后移动;

    offset 为负时,向前移动

  • origin:从何处开始计算偏移量。

    起始点常量名常量值
    文件开头SEEK_SET0
    当前位置SEEK_CUR1
    文件末尾SEEK_END2
#include <stdio.h>

int main(){
    FILE *fp = fopen("test.txt", "w+");
    fputs("123456789", fp);
    
    // 将文件指针移动到文件结尾
    fseek(fp, 0, SEEK_END);
    int len = ftell(fp); // 计算文件长度
    printf("len = %i\n", len);
    
    fclose(fp);
    
    return 0;
}
#include <stdio.h>

int main(){
    FILE *fp = fopen("test.txt","w+");
    
    fputs("123456789", fp);
    fseek( fp, 7, SEEK_SET );
    fputs("Hello", fp);
    
    fclose(fp);
    
    return 0;
}
  • 51
    点赞
  • 249
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AmosTian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值