前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >流动的代码:文件流畅读写的艺术(二)文件顺序读写函数

流动的代码:文件流畅读写的艺术(二)文件顺序读写函数

作者头像
用户11029103
发布2024-03-19 15:32:41
1150
发布2024-03-19 15:32:41
举报
文章被收录于专栏:技术学习

文件的顺序读写

fgetc 与 fputs

fgetc 函数用于从指定的文件流中读取下一个字符。如果成功,它返回读取到的字符;如果到达文件末尾或发生读取错误,它则返回 EOF

简单示例:

代码语言:javascript
复制
#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r");
    if (file) {
        int ch;
        while ((ch = fgetc(file)) != EOF) {
            putchar(ch);  // 将字符输出到标准输出
        }
        fclose(file);
    }
    return 0;
}

现在有一个test1.txt文件,我写入abcde,让fgetc读,并打印到屏幕上:

这里就是光标逐次往后移动。

fputc 函数用于向指定的文件流中写入一个字符

代码语言:javascript
复制
int fputc(int char, FILE *stream);
  • char 是要写入的字符。虽然参数类型是 int,但只会使用该 int 值的低 8 位(即一个字符)。
  • stream 是指向 FILE 对象的指针,代表要写入字符的文件流。通常,这个 FILE 对象是通过 fopen 函数获得的。

示例

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	FILE* pf = fopen("test1.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return -1;
	}
	fputc('a', pf);
	fputc('b', pf);
	fputc('c', pf);
	fputc('d', pf);

	fclose(pf);
	pf = NULL;
	return 0;
}

当然也可以用标准输出流打印到屏幕上

现在让我们做一个练习、

将test1.txt中的内容拷贝一份,生成test2.txt文件

从test1.txt中读取数据,写到test2.txt中。

首先,打开两个文件,分别进行读和写:

代码语言:javascript
复制
FILE* pfread = fopen("test1.txt", "r");
if (pfread == NULL)
{
	perror("fopen->test1.txt");
	return -1;
}
FILE* pfwrite = fopen("test2.txt", "w");
if (pfwrite == NULL)
{
	fclose(pfread);
	perror("fopen->test2.txt");
	return -1;
}

若第二个文件没有打开成功,则需要关闭第一个文件.

接着进行数据的读写

我们用fgetc读取,若读取不成功返回-1(EOF),那么我们可以使用while语句

代码语言:javascript
复制
int ch = 0;
while ((ch = fgetc(pfread)) != EOF)
{
	fputc(ch, pfwrite);
}

再讲返回的值写到test2.txt中 完整代码如下:

代码语言:javascript
复制
#include <stdio.h>
int main()
{
	FILE* pfread = fopen("test1.txt", "r");
	if (pfread == NULL)
	{
		perror("fopen->test1.txt");
		return -1;
	}
	FILE* pfwrite = fopen("test2.txt", "w");
	if (pfwrite == NULL)
	{
		fclose(pfread);
		perror("fopen->test2.txt");
		return -1;
	}
	int ch = 0;
	while ((ch = fgetc(pfread)) != EOF)
	{
		fputc(ch, pfwrite);
	}

	fclose(pfread);
	fclose(pfwrite);
	pfread = NULL;
	pfwrite = NULL;
	return 0;
}

fgets和fputs

fgets用于从文件流中读取字符串,其原型如下:

代码语言:javascript
复制
char *fgets(char *str, int num, FILE *stream);
  • char *str: 指向用于接收读取到的数据的字符数组的指针
  • int num: 指定最多要读取的字符数量(包括最后的 null 终止符 \0)
  • FILE *stream: 指定要读取的文件流

fgets 函数会从指定的文件流 stream 中读取字符,直到发生以下几种情况之一:

  • 读取了 num - 1 个字符
  • 遇到换行符 \n,换行符也会被读取并存入字符串中。
  • 遇到文件结束符(EOF)。

在任何情况下,fgets 都会在字符串末尾加上 null 终止符 \0 来确保字符串的正确终止。 这里我们可以通过观察代码来理解: 在test1.txt中放入abcdefgh,定义一个字符数组来读取:

代码语言:javascript
复制
int main()
{
	FILE* pf=fopen("test1.txt", "r");
	if (pf == NULL)
	{
		return 1;
	}
	char arr[20] = "xxxxxxxxxxxxxxxx";
	fgets(arr, 7, stdin);
	fclose(pf);
	pf = NULL;
	return 0;
}

fgets最多读取6个字符,最后补充一个/0; 调试如下:

如果函数执行成功,则返回 str(指向字符串的指针)。如果读取失败或遇到文件结束符且没有读取任何字符,则返回 NULL。

举例如下:

代码语言:javascript
复制
int main() {
    FILE* file;
    char buffer[100];

    // 打开文件
    file = fopen("test1.txt", "r");
    if (file == NULL) {
        perror("fopen");
        return -1;
    }

    // 使用fgets从文件中读取一行
    if (fgets(buffer, 100, file) != NULL) {
        printf("读取的字符串: %s\n", buffer);
    }
    else {
        printf("读取失败或文件已结束\n");
    }

    // 关闭文件
    fclose(file);

    return 0;
}

我们test1.txt中仍放入abcde; buffer用于接收 运行结果如下:

fputs用于向文件流中写入一个字符串,其原型如下:

代码语言:javascript
复制
int fputs(const char *str, FILE *stream);
  • const char *str:指向包含了你希望写入文件的以 null 结尾的字符串的指针
  • fputs 函数将字符串 str 写入到指定的文件流 stream 中,字符串的 null 终止符不写入到文件流。成功时,函数返回非负值;失败时,返回 EOF
  • 需要注意的是,fputs 函数不会为你自动添加换行符 \n,如果需要新的一行开始,则你需要显式地在字符串中包含 \n。

现在我们再进行演示,将test1.txt文件写入test2.txt中 首先,打开两个文件:

代码语言:javascript
复制
 char buffer[100];

 // 打开文件

 FILE* firead= fopen("test1.txt", "r");
 FILE* fiwrite= fopen("test2.txt", "w");
 if (firead == NULL) {
     perror("fopen->test.txt");
     return -1;
 }
 if (fiwrite == NULL) {
     perror("fopen->test2.txt");
     return -1;
 }

再进行读写:

代码语言:javascript
复制
while (fgets(buffer, 100, firead) != NULL) {
    if (fputs(buffer, fiwrite) != EOF)
    {
        printf("写入成功");
    }
    else
        printf("失败");
}
// 关闭文件
fclose(firead);
fclose(fiwrite);
return 0;

当然,也可以用stdin,和stdout进行标准输入和输出

fprintf和fscanf

讲fprintf之前,先提一下printf函数 printf:

代码语言:javascript
复制
int printf(const char *format, ...);
  • const char *format:格式字符串,用于指定输出的格式。
  • “…”:可变参数列表,提供了与格式字符串中的格式指定符相对应的输出值。 例如打印一个数字:
代码语言:javascript
复制
printf("%d",num);

而fprintf函数,它的原型如下:

代码语言:javascript
复制
int fprintf(FILE *stream, const char *format, ...);

与printf不同的是它多了一个流; fprintf 会根据提供的格式字符串,将数据格式化后写入指定的文件流。它在成功写入时返回写入的字符数,失败时返回负值。 对比

  • 输出目标:fprintf 用于向文件写入数据,而 printf 用于向**标准输出(如终端或控制台)**写入数据。
  • 第一个参数:fprintf 需要一个额外的 FILE 参数*来指定输出的文件,而 printf 直接将输出发送到标准输出。
  • 用途:fprintf 更适用于文件操作,如日志记录、数据保存等;printf 主要用于与用户的交互、程序的调试信息输出等。

例如:

代码语言:javascript
复制
FILE *file = fopen("output.txt", "w");
if (file != NULL) {
    fprintf(file, "The number is: %d\n", 42);
    fclose(file);
}

打开一个output.txt的文件,写入The number is: a这部分内容

fscanf fscanf 函数从文件流读取格式化输入

代码语言:javascript
复制
int fscanf(FILE *stream, const char *format, ...);

fscanf 会尝试按照指定的格式从文件流中读取数据,并将读取的数据存储在提供的地址上。成功时,它返回成功匹配并赋值的数据项数量****(读取成功n个则返回n)。如果到达文件末尾或发生读取错误,它返回 EOF

同样对比scanf函数:

代码语言:javascript
复制
int scanf(const char *format, ...);

scanf 与 fscanf 非常相似,唯一的区别是 scanf 读取标准输入(如用户在键盘上的输入),而不是从一个文件流读取。它同样返回成功匹配并赋值的数据项数量,或者在遇到输入错误时返回 EOF对比

  • 数据来源:最主要的区别是 fscanf 从文件或指定的输入流读取,而 scanf 从**标准输入(如键盘)**读取。
  • 用途:fscanf 常用于读取文件中的数据,而 scanf 常用于从用户手动输入中读取数据。
  • 第一个参数:fscanf 需要一个额外的 FILE 参数*来指定输入流,而 scanf 默认从标准输入读取数据。

假设从写好的output文件中读取

代码语言:javascript
复制
int main() {
    FILE* file = fopen("output.txt", "r"); // 打开文件用于读取
    int a;

    if (file != NULL) {
        // 使用fscanf读取文件中的整数
        if (fscanf(file, "The number is: %d\n", &a) == 1) {
            fprintf(stdout,"读取的整数是:%d\n", a);
        }
        else {
            fprintf(stdout,"读取失败\n");
        }
        fclose(file); // 关闭文件
    }
    else {
        perror("打开文件失败");
        return 1;
    }

    return 0;
}

stdout为标准输出,打印到屏幕上;

fread和fwirte

与上面六种函数不同的是,上述函数均为文本类或字符类输入输出,而fread和fwrite函数用于二进制的输入和输出fwrite fwrite 函数用于向文件中写入数据,它的函数原型:

代码语言:javascript
复制
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
  • const void *ptr 是指向要写入的数据的指针。
  • size_t size 是每个数据项大小(字节为单位)。
  • size_t nmemb 是要写入的数据项的个数。

举例:现在将数字1000写入我的output.txt文件中:

代码语言:javascript
复制
int main() {
    FILE *file;
    int number = 1000;

    // 打开文件用于二进制写入
    file = fopen("output.txt", "wb");
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 使用fwrite写入二进制数
    fwrite(&number, sizeof(int), 1, file);

    // 关闭文件
    fclose(file);

    return 0;
}

我们会发现它的内容是不可读的 我们再用fread读取. fread

代码语言:javascript
复制
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

我们会发现两个函数参数相同,无非就是一个读,一个写; 那么用fread读取刚刚的output.txt文件:

代码语言:javascript
复制
#include <stdio.h>

int main() {
    FILE *file;
    int number;

    // 打开文件用于二进制读取
    file = fopen("output.txt", "rb");
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 使用fread读取二进制数
    size_t itemsRead = fread(&number, sizeof(int), 1, file);
    if (itemsRead == 1) {
        printf("读取的整数是:%d\n", number);
    } else {
        // 如果没有读取到一个整数,打印错误信息
        if (feof(file)) {
            printf("文件结束,未读取到数据。\n");
        }
        if (ferror(file)) {
            printf("读取文件时出错。\n");
        }
    }

    // 关闭文件
    fclose(file);

    return 0;
}

本篇文章到此结束,后期为大家补充剩余的内容!感谢观看

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-01-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文件的顺序读写
    • fgetc 与 fputs
      • fgets和fputs
        • fprintf和fscanf
          • fread和fwirte
          相关产品与服务
          数据保险箱
          数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档