文件初阶入门(葵花宝典)

1. 文件的顺序读写

1.1 顺序读写函数的介绍

函数名     功能                    适用于

fgetc        字符输入函数      所有输入流

fputc        字符输出函数      所有输出流

fgets        文本行输入函数  所有输入流

fputs        文本行输出函数   所有输出流

fscanf      格式化输入函数   所有输入流

fprintf       格式化输出函数   所有输出流

fread        二进制输入           文件输入流

fwrite        二进制输出           文件输出流

上面的适用于所有输入流一般指适用于标准输入流和其他输入流(如文件输入流); 所有输出流一般指适用于标准输出流和其他输出流(如文件输出流)。

1.2 对比一组函数

1.2.1 scanf/fscanf/sscanf

1.2.2 printf/fprintf/sprintf

2. 文件的随机读写

2.1 fseek

根据文件指针的位置和偏移量来定位文件指针(文件内容的光标)

int fseek ( FILE * stream, long int offset, int origin );

例子:

#include<stdio.h>
int main()
{
    FILE* pf = fopen("data.txt", "wb");
    fputs("This is an apple", pf);
    fseek(pf, 9, SEEK_SET);
    fputs(" sam", pf);
    fclose(pf);
    return 0;
}

2.2 ftell

返回文件指针相对于起始位置的偏移量

long int ftell ( FILE * stream );

int main()
{
    long size;
    FILE* pf = fopen("data.txt", "rb");
    if (pf = NULL)
    {
        perror("Error opening file ");
    }
    else
    {
        feek(pf, 0, SEEK_END);
        size = ftell(pf);
        fclose(pf);
        printf("Size of myfile.txt: %ld bytes\n", size);
    }
    return 0;
}

2.3 rewind

让文件指针位置回到文件的起始位置。

void rewind ( FILE * stream );

int main()
{
    int n;
    FILE* pf;
    char buf[27];
    pf = fopen("data.txt", "w+");
    for (n = 'A'; n <= 'Z'; n++)
    {
        fputc(n, pf);
    }
    rewind(pf);
    fread(buf, 1, 26,pf);
    fclose(pf);
    buf[26] = '\0';
    printf("buf");
    return 0;
}

3. 文件读取结束的判定

3.1 被错误使用feof

在文件读取过程中,不能使用feof函数的返回值直接判断文件是否结束。

feof的作用是:当文件读取结束的时候,判断读取结束原因是否是:遇到文件末尾结束。

1. 文件读取是否结束,判断返回值为EOF(fgetc),或者NULL(fgets)

2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。

例如:

fread判断返回值是否小于实际要读的个数。

文本文件例子:

# include <stdio.h>
# include <stdlib.h>
int main ( void )
{
int c; // 注意: int ,⾮ char ,要求处理 EOF
FILE* fp = fopen( "test.txt" , "r" );
if (!fp) {
perror( "File opening failed" );
return EXIT_FAILURE;
}
//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回 EOF
while ((c = fgetc(fp)) != EOF) // 标准 C I/O 读取⽂件循环
{
putchar (c);
}
// 判断是什么原因结束的
if (ferror(fp))
puts ( "I/O error when reading" );
else if (feof(fp))
puts ( "End of file reached successfully" );
fclose(fp);
}
二进制文件例子;
#include <stdio.h>
enum { SIZE = 5 };
int main(void)
{
	double a[SIZE] = { 1.,2.,3.,4.,5. };
	FILE* fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式
	fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组
	fclose(fp);
	double b[SIZE];
	fp = fopen("test.bin", "rb");
	size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组
	if (ret_code == SIZE) {
		puts("Array read successfully, contents: ");
		for (int n = 0; n < SIZE; ++n)
			printf("%f ", b[n]);
		putchar('\n');
	}
	else { // error handling
		if (feof(fp))
			printf("Error reading test.bin: unexpected end of file\n");
		else if (ferror(fp)) {
			perror("Error reading test.bin");
		}
	}
	fclose(fp);
}

4. 文件缓冲区

ANSIC 标准采⽤“缓冲⽂件系统” 处理的数据⽂件的,所谓缓冲⽂件系统是指系统⾃动地在内存中为
程序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓
冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输
⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓
冲区的⼤⼩根据C编译系统决定的
#include <stdio.h>
#include <windows.h>
//VS2022 WIN11环境测试
int main()
{
 FILE*pf = fopen("test.txt", "w");
 fputs("abcdef", pf);//先将代码放在输出缓冲区
 printf("睡眠10秒-已经写数据了,打开test.txt⽂件,发现⽂件没有内容\n");
 Sleep(10000);
 printf("刷新缓冲区\n");
 fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到⽂件(磁盘)
 //注:fflush 在⾼版本的VS上不能使⽤了
 printf("再睡眠10秒-此时,再次打开test.txt⽂件,⽂件有内容了\n");
 Sleep(10000);
 fclose(pf);
 //注:fclose在关闭⽂件的时候,也会刷新缓冲区
 pf = NULL;
 return 0;
}

结论:因为有缓冲区的存在,C语⾔在操作⽂件的时候,需要做刷新缓冲区或者在⽂件操作结束的时候关闭⽂件。

相关推荐

  1. 面试:MySQL索引进深度分析

    2024-06-15 12:52:01       20 阅读
  2. c++入门

    2024-06-15 12:52:01       10 阅读
  3. 终极Linux命令:从入门到精通,一网打尽!

    2024-06-15 12:52:01       27 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-15 12:52:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-15 12:52:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-15 12:52:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-15 12:52:01       20 阅读

热门阅读

  1. SpringBoot 项目,三种方式实现打印 sql 日志

    2024-06-15 12:52:01       11 阅读
  2. Redis作为缓存

    2024-06-15 12:52:01       9 阅读
  3. Python+Opencv是实现车牌自动识别

    2024-06-15 12:52:01       6 阅读
  4. 面试问题-除了threading还会哪种并发

    2024-06-15 12:52:01       8 阅读
  5. 媒体查询的屏幕尺寸范围

    2024-06-15 12:52:01       8 阅读
  6. LeetCode 7题:整数翻转(原创)

    2024-06-15 12:52:01       8 阅读
  7. 使用静态方法接受对象参数

    2024-06-15 12:52:01       9 阅读
  8. SpringBoot集成websocket

    2024-06-15 12:52:01       10 阅读
  9. 基于starknet构建应用链之Madara

    2024-06-15 12:52:01       11 阅读
  10. 算法训练营day59

    2024-06-15 12:52:01       6 阅读
  11. SpringBoot集成Elasticsearch实例

    2024-06-15 12:52:01       9 阅读
  12. 什么是JWT?为什么用JWT?JWT的实战案例

    2024-06-15 12:52:01       7 阅读