C指针编程之道(四)- 指向文件类型的指针

文件结构体和文件指针

// 在c语言中,对文件的操作一般是用库函数来实现的
// ANSI(美国国家标准学会)规定了标准的输入输出函数,用他们对文件进行读写以规范和提高编程效率
// 每个被使用的文件在内存中都会开辟一个区,用来存放文件的有关信息,而这些信息都保存在文件结构体FILE中
// FILE 用于访问一个流,若同时激活了几个流,那么每个流都有一个相应的FILE与之相关联
// 为了在流上执行一些操作,需要调用一些合适的库函数,并传递一个与流相关的FILE参数
// C语言定义了三个特别的文件指针常数,标准输入、标准输出、标准错误,流的名称分别为stdin、stdout、stderr,他们都是一个指向FILE的指针

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

// 有了结构体FILE,我们就可以用它来定义FILE类型的变量,用来存放待处理文件的信息
FILE arrayf[10];

// 我们还可以定义一个文件类型的指针,即指向文件的指针
FILE *fp;


标准流的I/O函数

数据类型     输入       输出             描述
----------------------------------------------------------
字符       getchar     putchar     读取(写入)单个字符
文本行      fgets       fputs       文本行未格式化的输入(输出)
           scanf       printf      文本行格式化的输入(输出)
----------------------------------------------------------


# include <stdio.h>
int main() {
    char ch;
    //char s[10];

    //printf("请输入单个字符: ");
    //ch = getchar();
    //putchar(ch);

    //printf("请输入单个字符串: ");
    //fgets(s, sizeof(s)/sizeof(char), stdin);
    //fputs(s, stdout);

    printf("请输入一个字符: ");
    scanf(" %c", &ch);
    printf("%c\n", ch);

    return 0;
}


常见文件操作函数

打开与关闭:fopen,fclose
读写字符:fgetc,fputc
读写字符串:fgets,fputs
按数据块读写:fread,fwrite
格式化读写:fscanffprintf
文件定位:fseek,rewind,ftell
判断文件是否结尾:feof

fopen
函数原型:FILE * fopen(char const *name, char *mode)
相关解释:用于打开一个特定的文件,并把一个流和这个文件相关联

fclose
函数原型:int fclose(FILE *fp)
相关解释:用于关闭一个特定的文件,所谓关闭就是使文件指针变量不再指向该文件,之后不能再通过该指针变量对文件进行读写操作。
         对于输出流,fclose函数在文件关闭之前会刷新缓冲区,这里需要注意,在程序结束之前,我们一定要关闭所有已经打开
         的文件,否则会产生数据的丢失。比如,在向文件写数据时,总是先将数据存到缓冲区,待缓冲区满后才将数据写入文件,
         若缓冲区未满时程序结束,则缓冲区的数据将会丢失。使用fclose函数关闭文件,他会将缓冲区的数据写入文件,然后才
         释放文件指针,从而可以避免文件的丢失。fclose有一个int类型的返回值,文件关闭成功时返回0,失败时返回EOF(-1)

fgetc
函数原型:int fgetc(FILE *fp)
相关解释:从指定的文件读取一个字符,该文件必须是以只读或读写的方式打开的。fgetc从fp中读出一个字符并返回这个字符的ASCII码,
        若读到文件结束符,则函数返回文件结束标志。

fputc
函数原型:int fputc(int c, FILE *fp)
相关解释:把一个字符写到文件中,若写入成功则返回写入字符的ASCII码,若失败则返回EOF。

fgets
函数原型:char * fgets(char *s, int n, FILE *fp)
相关解释:从fp指向的文件中读取字符,当读到回车符、文件末尾、或满n-1个字符时 就在字符串末尾加上'\0',把他们存放到字符数组s
        中后函数返回,若在任何字符读取钱就达到了文件末尾,fgets就返回NULL指针(用于检查是否到达文件尾),否则返回s的首地址

fputs
函数原型:int * fputs(const char *s, FILE *fp)
相关解释:向指定的文件中输入一个字符串,若写入成功则返回0,否则返回EOF。

fread
函数原型:unsigned fread(void *s, unsigned size, unsigned count, FILE *fp)
相关解释:从fp指向的文件中读取二进制数据块到s数组,函数有四个参数
        第一个参数s是从文件中读物数据的存放地址,
        第二个参数size是要读的字节数的大小,
        第三个参数count是要读取多少个size字节的数据,即最多允许读取的数据块的个数,
        第四个参数fp为指向要读取的文件的指针

fwrite
函数原型:unsigned fwrite(void *s, unsigned size, unsigned count, FILE *fp)
相关解释:将二进制数据块s写入到fp指向的文件,函数有四个参数
        第一个参数s是要向文件写入的数据的存放地址,
        第二个参数size是要写的字节数的大小,
        第三个参数count是要写多少个size字节的数据,即最多允许写的数据块的个数,
        第四个参数fp为指向要写入的文件的指针
        返回值1表示写入成功,0表示写入失败

fprintf
函数原型:int fprintf(FILE *fp, const char *format, ...)
相关解释:fprintf函数与printf函数相似,都是格式化输出函数,不同的是printf输出的位置是终端,而fprintf输出的位置是文件

fscanf
函数原型:int fscanf(FILE *fp, const char *format, ...)
相关解释:fscanf函数与scanf函数相似,都是格式化输入函数,不同的是scanf输入的位置是终端,而fscanf输入的位置是文件
        [注] 用fprintffscanf对文件进行读写,在读入时需要将ASCII码转化成二进制数,在输出时又需将二进制数转化为
            字符,时间开销会比较大,因此交换数据比较频繁的情况下最好不要用这两个函数。

fseek
函数原型:int fseek(FILE *fp, long offset, int from)
相关解释:FILE中有一个指向当前位置的位置指针,如果顺序读写文件,每次读取一个字符,读完一个字符之后,位置指针自动移动到下
         一个字符。此外我们可以通过函数改变这个指针的位置实现对文件的随机读写,这样的函数就是文件定位函数,fseek就是这
         样一个文件定位函数,该函数可以改变文件的位置指针所指向位置,也就是改变下一个读取或写入位置。fseek有三个参数,
         第一个参数fp指向要操作文件的指针;
         第二个参数offset是位移量,它是以起始点为基点,向前移动的字节数;
         第三个参数from为开始定位的起始点。
         其中from的取值可以有如下三个(offset可以为负数):
             0    SEEK_SET    定位起始点为文件的开始
             1    SEEK_CUR    定位起始点为文件位置指针当前的位置
             2    SEEK_END    定位起始点为文件的末尾

rewind
函数原型:void rewind(FILE *fp)
相关解释:rewind为文件定位函数,作用是使文件的位置指针重新返回到文件的开头,它同时清除流的错误提示标志。

ftell
函数原型:long ftell(FILE *fp)
相关解释:得到文件指针的当前位置,用相对文件开头的位移量来表示,出错时返回-1L,这个函数可以让你保存一个文件的当前位置,这样
        可以在将来再次返回到这个位置。在二进制文件中,返回值就是当前位置到文件头的字节数;在文本文件中,不一定是当前位置到
        文件头的字节数,因为有的系统会对行末字符进行转换。

feof
函数原型:int feof(FILE *fp)
相关解释:用于判断文件是否结束,当文件指针指向fp末尾时,函数返回真,否则返回0


相关测试:

/**
* 复制文件,一次读取一个字符
*/

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

int main() {
    FILE *fpr, *fpw;
    FILE * open_file(const char *, const char *);

    //打开文件
    fpr = open_file("/Users/zhangqingli/Desktop/test.txt", "r");
    fpw = open_file("/Users/zhangqingli/Desktop/test2.txt", "w");

    //复制原文件内容到目标文件,每次只读取一个字符
    char ch;
    while ((ch=fgetc(fpr)) != EOF) {
        printf("%c", ch);
        fputc(ch, fpw);
    }

    //关闭文件
    fclose(fpr);
    fclose(fpw);

    return 0;
}

//打开一个文件
FILE * open_file(const char *filename, const char *mode) {
    FILE * fp = fopen(filename, mode);
    if (fp==NULL) {
        printf("文件打开失败!\n");
        exit(1);
    }
    return fp;
}



/**
* 复制文件,一次读取或写入一个字符串
*/

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

# define BUFFER_SIZE 10

int main() {
    FILE *fpr, *fpw;
    FILE * open_file(const char *, const char *);

    //打开文件
    fpr = open_file("/Users/zhangqingli/Desktop/test.txt", "r");
    fpw = open_file("/Users/zhangqingli/Desktop/test2.txt", "w");

    //复制原文件内容到目标文件,一次复制一个字符串
    char buffer[BUFFER_SIZE];
    while ((fgets(buffer, BUFFER_SIZE, fpr))) {
        printf("%s", buffer);
        fputs(buffer, fpw);
    }

    //关闭文件
    fclose(fpr);
    fclose(fpw);

    return 0;
}

//打开一个文件
FILE * open_file(const char *filename, const char *mode) {
    FILE * fp = fopen(filename, mode);
    if (fp==NULL) {
        printf("文件打开失败!\n");
        exit(1);
    }
    return fp;
}



/**
* 从键盘输入3个关于图书的数据,存入文件,再从文件中取出数据,显示到控制台上
*/

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

# define MIX_SIZE 3

struct book_info {
    char name[20];
    char author[20];
} book_array[MIX_SIZE];

FILE * open_file(const char *filename, const char *mode);
int save_book_info(const char *filename);
int display_book_info(const char *filename);

int main() {
    //初始化图书信息
    printf("初始化图书的信息如下\n");
    for (int i=0; i<MIX_SIZE; i++) {
        printf("请输入图书名称:");
        scanf(" %s", book_array[i].name);
        printf("请输入图书的作者:");
        scanf(" %s", book_array[i].author);
    }

    //core
    const char *filename = "/Users/zhangqingli/Desktop/test.txt";
    if (save_book_info(filename)) {
        display_book_info(filename);
    }

    return 0;
}

//打开一个文件
FILE * open_file(const char *filename, const char *mode) {
    FILE * fp = fopen(filename, mode);
    if (fp==NULL) {
        printf("文件打开失败!\n");
        exit(1);
    }
    return fp;
}

//保存图书信息到文件
int save_book_info(const char *filename) {
    FILE * fpw;

    //打开要写的文件
    fpw = open_file(filename, "w");

    //将图书信息存入待写入文件
    for (int i=0; i<MIX_SIZE; i++) {
        int status = (int) fwrite(&book_array[i], sizeof(struct book_info), 1, fpw);
        if (status != 1) {
            printf("文件写入出错!\n");
            return 0;
        }
    }

    //关闭文件
    fclose(fpw);
    return 1;
}

//从文件读取图书信息到控制台
int display_book_info(const char *filename) {
    FILE * fpr;

    //打开要读取的文件
    fpr = open_file(filename, "r");

    //将文件中的数据读出并显示
    for (int i=0; i<MIX_SIZE; i++) {
        fread(&book_array[i], sizeof(struct book_info), 1, fpr);
        printf("%s\t%s\n", book_array[i].name, book_array[i].author);
    }

    //文件关闭
    fclose(fpr);
    return 1;
}


/**
* 计算一个文件的大小
*/

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

FILE * open_file(const char * filename, const char * mode);
long file_size(FILE * fp);

int main() {

    FILE * fpr = open_file("/Users/zhangqingli/Desktop/test.txt", "r");
    long length = file_size(fpr);
    printf("文件的大小为:%ld byte\n", length);

    return 0;
}

//打开文件
FILE * open_file(const char * filename, const char * mode) {
    FILE * fp;

    fp = fopen(filename, mode);
    if (fp==NULL) {
        printf("文件打开失败!\n");
        exit(1);
    }
    return fp;
}

//计算文件大小
long file_size(FILE * fp) {
    long curpos, length;

    //计算文件大小
    curpos = ftell(fp);
    fseek(fp, 0L, SEEK_END);
    length = ftell(fp);

    //恢复文件指针到当前位置
    fseek(fp, curpos, SEEK_SET);

    return length;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值