C语言-文件操作

1. 文件指针

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 类型变量。通过文件指针对它所指的文件进行各种操作。

2. 文件的打开(fopen)

#include <stdio.h>

FILE *fopen(const char *path, const char *mode);

参数:

  • path:需要打开的文件名/文件路径
  • mode:打开文件的模式

返回值:

  • 成功:文件指针
  • 失败:NULL

2.1 打开模式

打开模式说明
w / wb以只读方式打开一个文本文件,若文件不存在则报错
w / wb以写方式打开文件,文件存在则清空文件,文件不存在则创建一个文件
a / ab以追加方式打开文件,在末尾添加内容,文件不存在则创建文件
r+ / rb+以可读、可写的方式打开文件,不创建新文件
w+ / wb+以可读、可写的方式打开文件,文件存在则清空文件,文件不存在则创建一个文件
a+ / ab+以添加方式打开文件,打开文件并在末尾追加文件,文件不存在则创建文件
  • b 是二进制模式的意思,b 只是在 Windows 有效,在 Linux 下 r 和 rb 的结果是相同的
  • 在 Windows 平台下,以“文本”方式打开文件,不加 b
  • 读取文件的时候,系统会将所有的 “\r\n” 转换成 “\n”
  • 写入文件的时候,系统会将 “\n” 转换成 “\r\n” 写入
  • 以"二进制"方式打开文件,则读\写都不会进行这样的转换
  • 在 Unix/Linux 平台下,“文本”与“二进制”模式没有区别,“\r\n” 作
    为两个字符原样输入输出

2.2 文件的关闭(fclose)

#include <stdio.h>

int fclose(FILE *fp);

关闭先前fopen()打开的文件。关闭时将缓冲区的数据写入文件中,并释放系统所提供的文件资源。
参数:

  • stream:文件指针
    返回值:
  • 成功:0
  • 失败:-1

注:

  • 文件在使用后应该关闭,打开的文件会占用内存资源,打开不关闭,会消耗内存
  • 一个进程同时打开的文件数是有限制的,超过最大同时打开文件数,再次调用 fopen 打开文件会失败
  • 如果没有明确的调用 fclose 关闭打开的文件,那么程序在退出的时候,操作系统会统一关闭

3. 文件的读写

3.1 文件的按块读写(fread、fwrite)

3.1.1 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 * nmemb
  • stream:已经打开的文件指针

返回值:

  • 成功:实际成功写入文件数据的块数目,此值和nmemb相等
  • 失败:0

3.1.2 fread

#include <stdio.h>

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

参数:

  • ptr:存放读取出来数据的内存空间
  • size: size_t 为 unsigned int类型,指定读取文件内容的块数据大小
  • nmemb:读取文件的块数,读取文件数据总大小为:size * nmemb
  • stream:已经打开的文件指针

返回值:

  • 成功:实际成功读取到内容的块数,如果此值比nmemb小,但大于0,说明读到文件的结尾。
  • 失败:0

###3.1.3 读取文件

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Test {
    int a;
    char c;
};

int main() {
    FILE *fp;

    struct Test data = {100, 'a'};
    struct Test data2;

    fp = fopen("./file2", "w+");
    int n_write = fwrite(&data, sizeof(struct Test), 1, fp);
    fseek(fp, 0, SEEK_SET);

    int n_read = fread(&data2, sizeof(struct Test), 1, fp);
    printf("read %d, %c\n", data2.a, data2.c);

    fclose(fp);
    return 0;
}

3.2 文件随机读写

#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:已经打开的文件指针

3.3 文件结尾(feof)

在 C 语言中,EOF 表示文件结束符(end of file)。在 while 循环中以 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:没有到文件结尾

3.4 按字符读写文件 (fgetc、fputc)

3.4.1 fputc

#include <stdio.h>
int fputc(int ch, FILE * stream);

将ch转换为unsigned char后写入stream指定的文件中
参数:

  • ch:写入文件的字符
  • stream:文件指针

返回值:

  • 成功:成功写入文件的字符
  • 失败:返回-1

3.4.2 fgetc

#include <stdio.h>
int fgetc(FILE * stream);

从指定的文件中读取一个字符
参数:

  • stream:文件指针

返回值:

  • 成功:返回读取到的字符
  • 失败:-1

3.4.3 读写案例

#include <stdio.h>
#include <string.h>

int main() {
    FILE *fp;
    char *s = "hello abc";
    int len = strlen(s);
    int i;

    fp = fopen("./file3", "w+");
    for (i = 0; i < len; i++) {
        fputc(*s, fp);
        s++;
    }

    rewind(fp);
    char ch = fgetc(fp); // 先读一次,防止输出文件结束符
    while (!feof(fp)) {
        printf("%c", ch);
        ch = fgetc(fp);
    }
    printf("\n");
    fclose(fp);
    return 0;
}

3.5 按行读写文件 (fgets、fputs)

3.5.1 fputs

#include <stdio.h>
int fputs(const char * str, FILE * stream);

将str所指定的字符串写入到stream指定的文件中,字符串结束符 ‘\0’ 不写入文件。

  • 参数:
  • str:字符串
  • stream:文件指针

返回值:

  • 成功:0
  • 失败:-1

3.5.2 fgets

#include <stdio.h>
char * fgets(char * str, int size, FILE * stream);

从stream指定的文件内读入字符,保存到str所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止,最后会自动加上字符 ‘\0’ 作为字符串结束。
参数:

  • str:字符串
  • size:指定最大读取字符串的长度(size - 1)
  • stream:文件指针

返回值:

  • 成功:成功读取的字符串
  • 读到文件尾或出错: NULL

3.5.3 案例

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    FILE *fp;
    char *s[] = {"ahfah\n", "alfja\n", "742492\n"};
    int len = 3;
    int i;

    fp = fopen("./file4", "w+");
    for (i = 0; i < len; i++) {
        int n = fputs(s[i], fp);
        printf("n=%d\n", n);
    }

    rewind(fp);
    char buf[128] = {0};
    while (!feof(fp)) {
        memset(buf, 0, sizeof(buf));
        char *p = fgets(buf, sizeof(buf), fp);
        if (p != NULL) {
            printf("buf= %s\n", buf);
            printf("return %s \n", p);
        }
    }
    printf("\n");
    fclose(fp);
    return 0;
}

3.6 格式化读写文件( fprintf、fscanf)

3.6.1 fprintf

#include <stdio.h>
int fprintf(FILE * stream, const char * format, ...);

根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符 ‘\0’ 为止。
参数:

  • stream:已经打开的文件
  • format:字符串格式,用法和printf()一样

返回值:

  • 成功:实际写入文件的字符个数
  • 失败:-1

3.6.2 fscanf

#include <stdio.h>
int fscanf(FILE * stream, const char * format, ...);

从stream指定的文件读取字符串,并根据参数format字符串来转换并格式化数据。
参数:

  • stream:已经打开的文件
  • format:字符串格式,用法和scanf()一样

返回值:

  • 成功:参数数目,成功转换的值的个数
  • 失败: - 1

3.6.3 案例

#include <stdio.h>

int main() {
    FILE *fp;
    int a;
    int b;
    int c;

    fp = fopen("./file5", "w+");

    int wn = fprintf(fp, "%d %d %d\n", 1, 2, 3);
    printf("fprintf return %d\n", wn);
    rewind(fp);

    int rn = fscanf(fp, "%d %d %d\n", &a, &b, &c);
    printf("fscnaf return %d\n", rn);
    printf("a= %d, b= %d, c= %d\n", a, b, c);
    fclose(fp);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不知所云,

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

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

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

打赏作者

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

抵扣说明:

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

余额充值