C提高6—文件的基本概念

以下内容为本人看“传智播客”C++基础教程完整版视频所做的笔记

文件的基本概念

按文件的逻辑结构:

  • 记录文件:由具有一定结构的记录组成(定长和不定长)
  • 流式文件:由一个个字符(字节)数据顺序组成

按存储介质:

  • 普通文件:存储介质文件(磁盘、磁带等)
  • 设备文件:非存储介质(键盘、显示器、打印机等)

按数据的组织形式:

  • 文本文件: ASCII文件,每个字节存放一个字符的ASCII码
  • 二进制文件:数据按其在内存中的存储形式原样存放
    写文件
int main()
{
    errno_t err;
    char buf[] = "this is a test\n";
    FILE *fp;
    err = fopen_s(&fp, "./test.txt", "w+");
    //"w+",写读方式打开,如果文件不存在,则创建;如果文件存在,清空内容,再写
    fputs(buf, fp);



    printf("\n");
    system("pause");
    return 0;
}

在以下路径中生成文件“test.txt”
这里写图片描述

流概念

  流是一个动态的概念,可以将一个字节形象地比喻成一滴水,字节在设备、文件和程序之间的传输就是流,类似于水在管道中的传输,可以看出,流是对输入输出源的一种抽象,也是对传输信息的一种抽象。通过对输入输出源的抽象,屏蔽了设备之间的差异,使程序员能以一种通用的方式进行存储操作,通过对传输信息的抽象,使得所有信息都转化为字节流的形式传输,信息解读的过程与传输过程分离。
  C语言中,I/O操作可以简单地看作是从程序移进或移出字节,这种搬运的过程便称为流(stream)。程序只需要关心是否正确地输出了字节数据,以及是否正确地输入了要读取字节数据,特定I/O设备的细节对程序员是隐藏的。

文件处理方法

  • 缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区
  • 非缓冲文件系统:低级文件系统,由用户在程序中为每个文件设定缓冲区
    这里写图片描述

文件句柄(实际上就是一个结构体变量)

typedef struct
{
    short level; //缓冲区“满”或者“空”的程度
    unsigned flags; //文件状态标识
    char fd; //文件描述符
    unsigned char hold; //如无缓冲区不读取字符
    short bsize; //缓冲区的大小
    unsigned char *buffer; //数据缓冲区的位置
    unsigned ar; //指针,当前的指向
    unsigned istemp; //临时文件,指示器
    short token; //用于有效性的检查
}FILE;

文件操作API

fgetc  fputc   按照字符读写文件
fputs  fgets   按照行读写文件 (读写配置文件)
fread  fwirte   按照块读写文件 (大数据块迁移)
fprintf  fscanf  按照格式化进行读写文件

char ch;
    ch=fgetc(stdin);  //std -> 键盘
    fputc(ch, stdout); //stdout->屏幕
    fputc(ch,stderr); //stderr ->屏幕,错误信息

绝对路径和相对路劲的区别

绝对路径指的是:C:\Users\apple\Documents\C提高视频\03.txt【针对windows平台】
相对路径指的是:/,45度, ./, ../(建议)【针对linux和windows平台】
VS:编译代码时,相对于项目工程
直接运行可执行程序,相对于程序

int main()
{


    //用相对路径来读取文件时,一定要将文件与可执行程序放在一个文件夹中
    errno_t err;
    FILE *fp = NULL;
    err = fopen_s(&fp,"./03.txt", "r+");
        if (fp == NULL)
        {
            perror("fopen");
            system("pause");
            return -1;
        }
        printf("\n");
    system("pause");
    return 0;
}

下面举一个例子,以相对路径创建一个文件,并用fputc函数将字符串写入文件中:

void my_fputs(char *path)
{
    errno_t err;
    FILE *fp = NULL;
    err = fopen_s(&fp, path, "w+");
    if (fp == NULL)
    {
        perror("my_fputs fopen");
        return;
    }
    //写文件
    char buf[] = "this is a test for fputs";
    int n = strlen(buf);
    int i = 0;
    for (i = 0; i < n; i++)
    {
        //fputc的返回值是成功写入文件的字符
        int ch = fputc(buf[i], fp);
        printf("ch = %c\n", ch);
    }
    if (fp != NULL)
    {
        fclose(fp);
        fp = NULL;
    }
}

int main()
{

    my_fputs("../03.txt");//文件的存放方式是以相对路径存放的



    printf("\n");
    system("pause");
    return 0;
}

刚刚写文件自己编了一个my_fputs函数来实现,现在要实现读文件,再编一个my_fgets函数来实现,代码如下:

void my_fgets(char *path)
{
    FILE *fp = NULL;
    errno_t err;
    err = fopen_s(&fp, path, "r+");
    if (fp == NULL)
    {
        perror("my_fgets fopen");
        return;
    }
    char ch;
    while(ch = fgetc(fp) != EOF)
    {
        printf("%c",ch);
    }
    printf("\n");
    if(fp != NULL)
    {
        fclose(fp);
        fp = NULL;
    }

}

最后在main函数中调用my_fgets(“../03.txt”);就可以实现在显示屏上打印出“03.txt”文件中的字符串。
这里写图片描述

按照块读写文件

#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"


typedef struct
{
    char name[50];
    int id;
}Stu;


void my_fwrite(char *path)
{
    errno_t err;
    FILE *fp = NULL;
    err = fopen_s(&fp, path, "w+");
    if (fp == NULL)
    {
        perror("my_fputs fopen");
        return;
    }

    Stu s[3];
    int i = 0;
    char buf[50];

    for (i = 0; i < 3; i++)
    {
        sprintf_s(buf, "stu%d%d%d", i, i, i);
        strcpy_s(s[i].name, buf);

        s[i].id = i + 1;

    }

    //写文件
    //s,写入文件内容的内存首地址
    //sizeof(Stu):块数据的大小
    //3:写数据的块数。那么写文件数据的大小就是sizeof(Stu)*3
    //fp:文件指针
    //返回值ret为成功写入文件的块数目

    int ret = fwrite(s, sizeof(Stu),3,fp);
    printf("ret = %d\n", ret);
    if (fp != NULL)
    {
        fclose(fp);
        fp = NULL;
    }

}


void my_fread(char *path)
{
    errno_t err;
    FILE *fp = NULL;
    err = fopen_s(&fp, path, "r+");
    if (fp == NULL)
    {
        perror("my_fputs fopen");
        return;
    }

    Stu s[3];

    //读文件
    //s,要读的文件内容的内存首地址
    //sizeof(Stu):块数据的大小
    //3:写数据的块数。那么写文件数据的大小就是sizeof(Stu)*3
    //fp:文件指针
    //返回值ret为成功度取文件的块数目

    int ret = fread(s, sizeof(Stu), 3, fp);
    printf("ret = %d\n", ret);
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        printf("%s,%d\n", s[i].name, s[i].id);
    }

    if (fp != NULL)
    {
        fclose(fp);
        fp = NULL;
    }

}


int main()
{

    my_fwrite("../05.txt");
    my_fread("../05.txt");

    printf("\n");
    system("pause");
    return 0;
}

读写结果如下:
这里写图片描述

按照格式化读写文件

void my_fprintf(char *path)
{
    errno_t err;
    FILE *fp = NULL;
    err = fopen_s(&fp, path, "w+");
    if (fp == NULL)
    {
        perror("my_fprintf fopen");
        return;
    }


    fprintf(stdout,"hello,today is %d",20171206);  //和printf("hello,today is %d",20171206);功能一样
    fprintf(fp,"hello,today is %d",20171206);//写入文件中了


    if (fp != NULL)
    {
        fclose(fp);
        fp = NULL;
    }
}

void my_fscanf(char *path)
{
    errno_t err;
    FILE *fp = NULL;
    err = fopen_s(&fp, path, "r+");
    if (fp == NULL)
    {
        perror("my_fscanf fopen");
        return;
    }
    int a =0;
    fscanf(fp,"hello,today is %d",&a);
    printf("a = %d",a);

if (fp != NULL)
    {
        fclose(fp);
        fp = NULL;
    }
}

随机位置读文件

int fseek(FILE *stream,long offset,int whence);
//返回值:成功返回0,出错返回-1并设置errno; offset是偏移量;whence是参考点

long ftell(FILE *stream);
//返回值:成功返回当前读写位置,出错返回-1并设置errno;测光标移动的长度

void rewind(FILE *stream); //将光标恢复到文件最开始的地方

fseek函数中的参数offset和whence共同决定了读写位置移动到何处,whence参数的含义如下:
SEEK_SET:
从文件开头移动offset个字节
SEEK_CUR:
从当前位置移动offst个字节
SEEK_END:
从文件末尾向之前移动-offset个字节

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值