《C语言初阶进阶完整教程》- 已完结 - 文件操作

目录

前言

一、文件指针

        1.文件打开和关闭      

        2.打开方式 

         3.实现代码模板

二、文件顺序读写

        1.fputc(从文件里面读一个字符)

        2. 三种流

        3.fgetc(把一个字符写到文件中)

        4.fputs (整行输出)

         4.fgets (整行输入)

        5..拷贝文件

        6. fwrite(将一块内存区域中的数据写入到本地文本)二进制

        7.fread(从一个文件流中读取数据)二进制

        8.对比以下函数

三、文件随机读写 

        1.fseek

        2.ftell

        3 rewind

四、文本文件和二进制文件 

五、文件读取结束判定 

六、文件缓冲区 

总结


前言

 为什么使用文件什么是文件

文件的打开和关闭文件的顺序读写文件的随机读写

文本文件和二进制文件文件读取结束的判定文件缓冲区


一、文件指针

        1.文件打开和关闭      

//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
int fclose ( FILE * stream );

        2.打开方式 

         3.实现代码模板

/* fopen fclose example */
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
    FILE *pf= fopen ("myfile.txt","w");
    //文件操作
    if (pf==NULL)
    {
        //文件打开失败
        printf("%s\n",strerror(errno));
        return 0;
    }
    //写文件

    //关闭文件
    fclose(pf);
    pf= NULL;
}

二、文件顺序读写

        1.fputc(从文件里面读一个字符)

char fputc( char c, FILE *stream );

c:读取的字符

stream:对应的只指针

/* fopen fclose example */
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
    FILE *pf= fopen ("myfile.txt","w");
    //文件操作
    if (pf==NULL)
    {
        //文件打开失败
        printf("%s\n",strerror(errno));
        return 0;
    }
    //写文件
    
    //fput('a',pf);
    //fput('b',pf);
    //fput('c',pf);
    
    char ch = 0;
    for(ch = 'a'; ch <= 'z'; ch++){
        fputc(ch, pf);
    }

    //关闭文件
    fclose(pf);
    pf= NULL;
}

 结果:

        2. 三种流

标准输入流:stdin

标准输出流:stdout

标准错误流 :stderr

从键盘上输入内存时,就是将数据输入到标准输入流

从内存上输入显示器上时,就是将数据输入到标准输出流

使用:将指针替换为所需要的三种流即可。

        3.fgetc(把一个字符写到文件中)

int fgetc( FILE*stream );

stream:对应的只指针

/* fopen fclose example */
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    FILE* pf = fopen("myfile.txt", "w");
    //文件操作
    if (pf == NULL)
    {
        //文件打开失败
        printf("%s\n", strerror(errno));
        return 0;
    }
    //读文件

    int ch = fgetc(pf);
    printf("%c\n",ch);

    int ch = fgetc(pf);
    printf("%c\n", ch);

    int ch = fgetc(pf);
    printf("%c\n", ch);

    int ch = fgetc(pf);
    printf("%c\n", ch);

    //关闭文件
    fclose(pf);
    pf = NULL;
}

        4.fputs (整行输出)

int fputs(const char *s, FILE *stream);

把参数s指向的字符串写入stream指向的流,但不包括字符串末尾的空字符  

/* fopen fclose example */
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    FILE* pf = fopen("myfile.txt", "w");
    //文件操作
    if (pf == NULL)
    {
        //文件打开失败
        printf("%s\n", strerror(errno));
        return 0;
    }
    //读文件

    fputs("hello world",pf);

    //关闭文件
    fclose(pf);
    pf = NULL;
}

         4.fgets (整行输入)

char *  fgets(char * s, int n,FILE *stream);

从stream指向的输入流中读取 unsigned char 型的字符串                            

/* fopen fclose example */
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    FILE* pf = fopen("myfile.txt", "w");
    //文件操作
    if (pf == NULL)
    {
        //文件打开失败
        printf("%s\n", strerror(errno));
        return 0;
    }
    char buf[1000] = { 0 };
    //读文件

    fgets(buf, 1000, pf);
    printf("%s", buf);

    //关闭文件
    fclose(pf);
    pf = NULL;
}

        5..拷贝文件

#include<stdio.h>
#include<errno.h>
int main()//拷贝文件
{
	FILE* pr = fopen("text.txt", "r");
	if (pr == NULL)
	{
		printf("open for read:%s\n", strerror(errno));
		return 0;
	}
	FILE* pw = fopen("text2.txt","w");
	if (pr == NULL)
	{
		printf("open for write:%s\n", strerror(errno));
		close(pr);
		pr = NULL;
		return 0;
	}
	int ch=0;
	//拷贝文件
	while ((ch=fgetc(pr)) != EOF)
	{
		fputc(ch, pw);
	}
	//关闭文件
	fclose(pr);
	pr == NULL;
	fclose(pw);
	pw == NULL;
	return 0;
}

        6. fwrite(将一块内存区域中的数据写入到本地文本)二进制

size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
    -- buffer:指向数据块的指针
    -- size:每个数据的大小,单位为Byte(例如:sizeof(int)就是4)
    -- count:数据个数
    -- stream:文件指针

int main()
{
    struct stu s[2] - { {"张三",20,95.5}, { "lisi",16,66.5 } };
    FILE* pf = fopen("myfile.txt", "wb");
    //文件操作
    if (pf == NULL)
    {
        //文件打开失败
        printf("%s\n", strerror(errno));
        return 0;
    }
    //二进制打开
    fwrite(&s, sizeof(struct stu), 2, pf);

    //关闭文件
    fclose(pf);
    pf = NULL;
}

        7.fread(从一个文件流中读取数据)二进制

    size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
      -- buffer:指向数据块的指针
      -- size:每个数据的大小,单位为Byte(例如:sizeof(int)就是4)
      -- count:数据个数
      -- stream:文件指针

int main()
{
    struct stu s[2] = { 0 };
    FILE* pf = fopen("myfile.txt", "rb");
    //文件操作
    if (pf == NULL)
    {
        //文件打开失败
        printf("%s\n", strerror(errno));
        return 0;
    }
    //二进制读文件
    fread(s, sizeof(struct stu), 2, pf);

    printf("%s %d %lf\n",s[0].name, s[0].age, s[0].d);
    printf("%s %d %lf\n",s[1].name, s[1].age, s[1].d);

    //关闭文件
    fclose(pf);
    pf = NULL;
}

        8.对比以下函数

scanf从标准输入流(stdin)上进行格式化输入的函数
printf向标出输出流( stdout)上进行格式化的输出函数 

 fscanf可以从标准输入流(stdin)/指定的文件流上读取格式化的数据
fprintf把数据按照格式化的方式输出到标准输出流(stdout)/指定的文件流

fscanf()函数(有点像正则表达式):

功 能: 从一个流中执行格式化输入,fscanf遇到空格和换行时结束,注意空格时也结束。

用 法:int fscanf(FILE *stream, char *format,[argument...]);

int fscanf(文件指针,格式字符串,输入列表);

  fscanf(fp,"%s%d%lf",a,&b,&c)

  返回值:整型,数值等于[argument...]的个数
fprintf(pf, "%s %d %s", s.name, s.age, s.sex);//把数据写入文件

 sscanf可以从一个字符串中提取(转化)出格式化数据

sprintf把一个格式化的数据转换成字符串

int sscanf( const char *buffer, const char *format [, argument ] ... );

int sprintf( char *buffer, const char *format [, argument] ... );

三、文件随机读写 

        1.fseek

根据文件指针的位置和偏移量来定位文件指针.

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

描 述: 函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere为基准,偏移offset个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。

注意:
第一个参数stream为文件指针
第二个参数offset为偏移量,整数表示正向偏移,负数表示负向偏移
第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
其中SEEK_SET,SEEK_CUR和SEEK_END和依次为0,1和2.

简言之:
fseek(fp,100L,0);把fp指针移动到离文件开头100字节处;
fseek(fp,100L,1);把fp指针移动到离文件当前位置100字节处;
ffseek(fp,-100L,2);把fp指针退回到离文件结尾100字节处。

/* ftell example : getting size of a file */
#include <stdio.h>
int main ()
{
    FILE * pFile;
    long size;
    pFile = fopen ("myfile.txt","rb");
    if (pFile==NULL) perror ("Error opening file");
    else
    {
        fseek (pFile, 0, SEEK_END); // non-portable
        size=ftell (pFile);
        fclose (pFile);
        printf ("Size of myfile.txt: %ld bytes.\n",size);
    }
    return 0;
}

        2.ftell

long ftell(FILE *fp);

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

/* ftell example : getting size of a file */
#include <stdio.h>
int main ()
{
    FILE * pFile;
    long size;
    pFile = fopen ("myfile.txt","rb");
    if (pFile==NULL) perror ("Error opening file");
    else
    {
        fseek (pFile, 0, SEEK_END); // non-portable
        size=ftell (pFile);
        fclose (pFile);
        printf ("Size of myfile.txt: %ld bytes.\n",size);
    }
    return 0;
}

        3 rewind

void rewind ( FILE * stream );

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

/* rewind example */
#include <stdio.h>
int main ()
{
    int n;
    FILE * pFile;
    char buffer [27];
    pFile = fopen ("myfile.txt","w+");
    for ( n='A' ; n<='Z' ; n++)
    fputc ( n, pFile);
    rewind (pFile);
    fread (buffer,1,26,pFile);
    fclose (pFile);
    buffer[26]='\0';
    puts (buffer);
    return 0;
}

四、文本文件和二进制文件 

        二进制文件以二进制形式存储,文本文件以ASCII存储的。

        字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。

#include <stdio.h>
int main()
{
    int a = 10000;
    FILE* pf = fopen("test.txt", "wb");
    fwrite(&a, 4, 1, pf);//二进制的形式写到文件中
    fclose(pf);
    pf = NULL;
    return 0;
}
//0000 0000 0000 0000 0010 0111 0001 0000
// 0     0    0    0    2    7    1    0

 二进制结果:

五、文件读取结束判定 

牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。
而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束

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

        fgetc判断是否为EOF。

        fgets判断返回值是否为NULL。

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);
    }
    //判断是什么原因结束的
    //IO错误
    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);
}

六、文件缓冲区 

从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。

#include <stdio.h>
#include <windows.h>
//VS2013 WIN10环境测试
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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

penguin_bark

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

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

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

打赏作者

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

抵扣说明:

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

余额充值