C语言中的文件相关知识

一、文件概述
1、定义
时存储在外部介质上数据的集合,是操作系统数据管理的单位。
2、文件分类
(1)按存储介质:

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

(2)按数据的组织形式:

  • 文本文件: ASCI文件, 每个字节存放一个字符的ASCII码
  • 二进制文件:数据按其在内存中的存储形式原样存放

文本文件特点:存储量大、速度慢、便于对字符操作
二进制文件特点:存储量小、速度快、便于存放中间结果
在这里插入图片描述
3、文件处理方法
在这里插入图片描述
缓冲文件系统:
在这里插入图片描述
非缓冲文件系统:
在这里插入图片描述
二、文件类型指针
(1)文件结构体FILE

  • 缓冲文件系统为每个正使用的文件在内存开辟文件信息区
  • 文件信息用系统定义的名为FILE的结构体描述
  • FILE定义在stdio.h中

typedef struct
{ int _fd; //文件号
int _cleft; //缓冲区中剩下的字符数
int _mode; //文件操作方式
char *_next; //文件当前读写位置
char *_buff; //文件缓冲区位置
}FILE;

(2)文件类型指针

  • 指针变量说明: FILE *fp;
  • 用法:
    文件打开时,系统自动建立文件结构体,并把指向它的指针返回来,程序通过这个指针获得文件信息,访问文件
    文件关闭后,它的文件结构体被释放
    在这里插入图片描述
    三、文件的打开与关闭
  • C文件操作用库函数实现,包含在stdio.h
  • 文件使用方式:打开文件–>文件读/写–>关闭文件

(1)文件打开fopen

  • 函数原型: FILE *fopen(char *name,char *mode)
  • name为要打开的文件名,mode是文件的打开方式
  • 功能:按指定方式打开文件
  • 返回值:正常打开,为指向文件结构体的指针;打开失败,为NULL
  • 系统自动打开和关闭三个标准文件:
    标准输入------键盘 stdin
    标准输出------显示器 stdout
    标准出错输出-----显示器 stderr

在这里插入图片描述例 :

FILE *fp;
fp= fopen (“c:\fengyi\bkc\test.dat”,”r”);

FILE *fp;
char *filename=“c:\fengyi\bkc\test.dat”
fp= fopen(filename,”r”);

文件打开与测试
FILE *fp;
fp=fopen(“aa.c”,“w”);
if(fp==NULL)
{ printf(“File open error!\n”);
exit(0);
}

(2)文件关闭fclose

  • 作用:使文件指针变量与文件“脱钩”,释放文件结构体和文件指针

  • 函数原型:int fclose(FILE *fp)

  • 功能:关闭fp指向的文件

  • 返值:正常关闭为0;出错时,非0
    在这里插入图片描述
    四、文件的读写操作
    (1)fputc与fgetc

  • fputc
    函数原型:int fputc(int c, FILE *fp)
    功能:把一字节代码c写入fp指向的文件中
    返值:正常,返回c;出错,为EOF

  • fgetc
    函数原型:int fgetc(FILE *fp)
    功能:从fp指向的文件中读取一字节代码
    返值:正常,返回读到的代码值;读到文件尾或出错,为EOF

例1:从键盘输入字符,逐个存到磁盘文件中,直到输入‘#“为止

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define CARDPATH   "d:\\out.txt" 
int main()
{
 FILE *fp;
 char ch;
 if ((fp = fopen(CARDPATH,"w")) == NULL)
 {
  printf("cannot open file\n");
  return 0;
 }
 printf("Please input string:");
 ch = getchar();
 while (ch != '#')
 {
  fputc(ch, fp);
  putchar(ch);
  ch = getchar();
 }
 fclose(fp);
}

例2: 读文本文件内容并显示

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define CARDPATH   "d:\\out.txt" 
int main()
{
 FILE *fp;
 char ch;
 if ((fp = fopen(CARDPATH, "r")) == NULL)
 {
  printf("cannot open file\n");
 }
 while ((ch = fgetc(fp)) != EOF)
  putchar(ch);
 fclose(fp);
}

例3:文件拷贝

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
 FILE *in, *out;
 char ch, infile[20], outfile[20];
 scanf("%s", infile);
 scanf("%s", outfile);
 if ((in = fopen(infile, "r")) == NULL)
 {
  printf("Cannot open infile.\n");
 }
 if ((out = fopen(outfile, "w")) == NULL)
 {
  printf("Cannot open outfile.\n");
 }
 while (!feof(in))
  fputc(fgetc(in), out);
 fclose(in);
 fclose(out);
}

例4:
在这里插入图片描述
(2)fread与fwrite

  • 函数原型:
    size_t fread(void *buffer,size_t size, size_t count,FILE *fp)
    size_t fwrite(void *buffer,size_t size, size_t count,FILE *fp)
  • 功能:读/写数据块
  • 返值:成功,返回读/写的块数;出错或文件尾,返回0
  • 说明:
    -typedef unsigned size_t;
    -buffer: 指向要输入/输出数据块的首地址的指针
    -size: 每个要读/写的数据块的大小(字节数)
    -count: 要读/写的数据块的个数
    -fp: 要读/写的文件指针
    -fread与fwrite 一般用于二进制文件的输入/输出

例 1:
在这里插入图片描述
例 2:

struct  student
{    
      int num;
      char  name[20];
      char sex;
      int age;
      float  score[3];
}stud[10];
for(i=0;i<10;i++)
      fread(&stud[i],sizeof(struct  student),1,fp);

例 3: 从键盘输入2个学生数据,把他们转存到磁盘文件中去

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define SIZE 2
struct student_type
{
 char name[10];
 int num;
 int age;
 char addr[15];
}stud[SIZE];
void save()
{
 FILE *fp;
 int  i;
 if ((fp = fopen("d:\\out.txt", "wb")) == NULL)
 {
  printf("cannot open file\n");
  return;
 }
 for (i = 0; i < SIZE; i++)
  if (fwrite(&stud[i], sizeof(struct student_type), 1, fp) != 1)
   printf("file write error\n");
 fclose(fp);
}
void display()
{
 FILE *fp;
 int  i;
 if ((fp = fopen("d:\\out.txt", "rb")) == NULL)
 {
  printf("cannot open file\n");
  return;
 }
 for (i = 0; i < SIZE; i++)
 {
  fread(&stud[i], sizeof(struct student_type), 1, fp);
  printf("%-10s %4d %4d %-15s\n", stud[i].name,
   stud[i].num, stud[i].age, stud[i].addr);
 }
 fclose(fp);
}
int main()
{
 int i;
 for (i = 0; i < SIZE; i++)
  scanf("%s%d%d%s", stud[i].name, &stud[i].num,
   &stud[i].age, stud[i].addr);
 save();
 display();
}

(3)fprintf与fscanf

  • 函数原型
    int fprintf(FILE *fp,const char *format[,argument,…])
    int fscanf(FILE *fp,const char *format[,address,…])
  • 功能:按格式化对文件进行I/O操作
  • 返值:成功,返回I/O的个数;出错或文件尾,返回EOF

例1:

fprintf(fp,“%d,%6.2f”,i,t); //将i和t按%d,%6.2f格式输出到fp文件
fscanf(fp,“%d,%f”,&i,&t); //若文件中有3,4.5 ,则将3送入i, 4.5送入t

例2:从键盘按格式输入数据存到磁盘文件中去

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define CARDPATH   "d:\\out.txt" 
int main()
{
 char s[80], c[80];
 int a, b;
 FILE *fp;
 if ((fp = fopen(CARDPATH, "w")) == NULL)
 {
  puts("can't open file"); 
 }
 fscanf(stdin, "%s%d", s, &a);/*read from keaboard*/
 fprintf(fp, "%s  %d", s, a);/*write to file*/
 fclose(fp);
 if ((fp = fopen(CARDPATH, "r")) == NULL)
 {
  puts("can't open file");
 }
 fscanf(fp, "%s%d", c, &b);/*read from file*/
 fprintf(stdout, "%s %d", c, b);/*print to screen*/
 fclose(fp);
}

(4)fgets与fputs

  • 函数原型:
    char *fgets(char *s,int n,FILE *fp)
    int fputs(char *s,FILE *fp)
  • 功能:从fp指向的文件读/写一个字符串
  • 返值:
    fgets正常时返回读取字符串的首地址;出错或文件尾,返回NULL
    fputs正常时返回写入的最后一个字符;出错为EOF

注意:
fgets从fp所指文件读n-1个字符送入s指向的内存区,并在最后加一个‘\0’(若读入n-1个字符前遇换行符或文件尾(EOF)即结束)
②fputs把s指向的字符串写入fp指向的文件
例:从键盘读入字符串存入文件,再从文件读回显示

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<stdlib.h>
#define CARDPATH   "d:\\out.txt" 
int main()
{
 FILE  *fp;
 if ((fp = fopen(CARDPATH, "w")) == NULL)
 {
  printf("cann't open file");
  exit(0);
 }
 printf("input a string:\n");
    char ch = getchar();
 while (ch != '\n')
 {
  fputc(ch, fp);
        ch = getchar();
 }
 fclose(fp);
 if ((fp = fopen(CARDPATH, "r")) == NULL)
 {
  printf("cann't open file");
  exit(0);
 }
 ch = fgetc(fp);
    while (ch != EOF)
    {
  putchar(ch);
  ch = fgetc(fp);
 }
    printf("\n");
 fclose(fp);
}
 
 

五、文件的定位
(1)几个概念

  • 文件位置指针-----指向当前读写位置的指针
  • 读写方式
    顺序读写:位置指针按字节位置顺序移动,叫~
    随机读写:位置指针按需要移动到任意位置,叫~

(2)rewind函数

  • 函数原型: void rewind(FILE *fp)
  • 功能:重置文件位置指针到文件开头
  • 返值:无

例 对一个磁盘文件进行显示和复制两次操作

#include <stdio.h>
main()
{   FILE *fp1,*fp2;
    fp1=fopen("d:\\fengyi\\bkc\\ch12_4.c","r");
    fp2=fopen("d:\\fengyi\\bkc\\ch12_41.c","w");
    while(!feof(fp1))  putchar(getc(fp1));
    rewind(fp1);
    while(!feof(fp1))  putc(getc(fp1),fp2);
    fclose(fp1);
    fclose(fp2);
}

(3)fseek函数

  • 函数原型: int fseek(FILE *fp,long offset,int whence)
  • offset是位移量(以起始点为基点,移动的字节数)>0 向后移动 ;<0 向前移动
  • whence起始点
    文件开始 SEEK_SET 0
    文件当前位置 SEEK_CUR 1
    文件末尾 SEEK_END
  • 功能:改变文件位置指针的位置
  • 返值:成功,返回0;失败,返回非0值

(4)ftell函数

  • 函数原型: long ftell(FILE *fp)
  • 功能:返回位置指针当前位置(用相对文件开头的位移量表示)
  • 返值:成功,返回当前位置指针位置;失败,返回-1L

例 磁盘文件上有3个学生数据,要求读入第1,3学生数据并显示

#include <stdio.h>
struct student_type
{    int num;
     char name[10];
     int age;
     char addr[15];
}stud[3];
main()
{   
    int i;
    FILE *fp;
    if((fp=fopen("studat","rb"))==NULL)
    {   
       printf("can't open file\n");exit(0);   
    }
    for(i=0;i<3;i+=2)
    {   
         fseek(fp,i*sizeof(struct student_type),0);
         fread(&stud[i],sizeof(struct student_type),1,fp);
         printf("%s  %d  %d  %s\n",
           stud[i].name,stud[i].num,stud[i].age,stud[i].addr);
    }
    fclose(fp);
}

例 求文件长度

#include"stdio.h"
main()
{ 
    FILE *fp;
    char filename[80];
    long length;
    gets(filename);
    fp=fopen(filename,"rb");
    if(fp==NULL)
       printf("file not found!\n");
    else
    { 
      fseek(fp,0L,SEEK_END);
      length=ftell(fp);
      printf("Length of File is %1d bytes\n",length);
      fclose(fp);
    }
}

六、出错的检测
(1)ferror函数

  • 函数原型: int ferror(FILE *fp)
  • 功能:测试文件是否出现错误
  • 返值:未出错,0;出错,非0
  • 说明
    -每次调用文件输入输出函数,均产生一个新的ferror函数值,所以应及时测试
    -fopen打开文件时,ferror函数初值自动置为0

(2)clearerr函数

  • 函数原型: void clearerr(FILE *fp)
  • 功能:使文件错误标志置为0
  • 返值:无
  • 说明:出错后,错误标志一直保留,直到对同一文件调clearerr(fp)或rewind或任何其它一个输入输出函数

例 ferror()与clearerr()举例

#include <stdio.h>
int  main(void)
{    
    FILE *stream;
    stream = fopen("DUMMY.FILE", "w");
    getc(stream);
    if (ferror(stream))
    {  
        printf("Error reading from DUMMY.FIL\n");
        clearerr(stream);
     }
    if(!ferror(stream))
       printf("Error indicator cleared!");
    fclose(stream);
    return 0;
}

七、补充
解决fopen、fscanf 在VS中要求替换为fopen_s、fscanf_s的最全解决办法

方法一:在程序最前面加#define _CRT_SECURE_NO_DEPRECATE;

方法二:在程序最前面加#define _CRT_SECURE_NO_WARNINGS;

方法三:在程序最前面加#pragma warning(disable:4996);

方法四:把scanf、scanf改为scanf_s、fopen_s,具体方法请百度;

方法五:无需在程序最前面加那行代码,只需在新建项目时取消勾选“SDL检查”即可;

方法六:若项目已建立好,在项目属性里关闭SDL也行;

方法七:在工程项目设置一下就行;将报错那个宏定义放到 项目属性 – C/C+±- 预处理器 – 预处理器定义;

方法八:在 项目属性 – c/c++ – 命令行 添加:/D _CRT_SECURE_NO_WARNINGS 就行了。
参考链接:https://blog.csdn.net/zj371561267/article/details/81280972

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值