chapter 10 对文件的输入输出(中)

简介: chapter 10 对文件的输入输出

10.2.2 用fclose 函数关闭数据文件;


为什么要关闭文件,当建立了一个文件,你就建立缓冲区和程序区域的流动。举例子,当输入到程序区域时候,你只有缓冲区满了才可以。如果你不关闭文件,直接关闭程序,你的缓冲区的数据将会丢失。所以需要先关闭文件,也就是先把缓冲区的数据转到数据区域的时候,再把程序关闭。

怎么调用关闭函数:

fclose(文件指针)

fclose(fp);
切断指针的指向,关闭文件。



10.3 顺序读写数据文件


顺序读写就是按照数据在文件的物理顺序,读文件的时候,自上而下。写文件的时候也是如此。对文件的顺序读写一般需要借助库函数实现。


10.3.1怎么向文件读写字符

1670500382379.jpg

看上面库函数的函数;

fgetc(fp);//fp:指向所需要操作的文件;文件读出
fputc(fp);//fp:指向所需要操作的文件;写入文件


举个例子:

/*从键盘上输入一些字符,逐个把他们送到磁盘上去,
直到用户输入一个“#”为止*/ 
#include <stdio.h>
#include <stdlib.h>
int main()
{
  FILE *fp;//定义了一个指针变量,这个指针变量是用来指向文件的 
  char ch,filename[10];//定义了一个字符变量,和一个字符数组储存文件名 
  printf("please enter by-used  filename: ");
  scanf("%s",filename);
  if((fp=fopen(filename,"w"))==NULL)
  {
  printf("无法打开文件\n");
  exit(0);
  }
  //ch=getchar();//用来接受最后的回车符号 
  printf("请输入一个准备储存到磁盘的字符串(以#结束):");//输入一段字符串 
  ch=getchar();//接受字符串第一个字符; 
  while(ch!='#')
  {
  fputc(ch,fp);//写入文件第一个字符 
  putchar(ch);//输出第一个字符到文件 
  ch=getchar();//得到下一个字符 
  } 
  fclose(fp);//字符串全部输入完毕 ,关闭文件 
  putchar(10);//输出换行符 
  return 0;
}

1670500422079.jpg

exit函数的头文件是stdlib.h;

1670500464315.jpg

能在磁盘中看到。


再看一个例子

/*将一个磁盘文件的信息复制到宁外一个磁盘文件上;
今让之前的file.dat 的数据放置到file2.dat 上。*/ 
#include <stdio.h>
#include <stdlib.h>
int main()
{
  FILE *in,*out;//定义了两指针变量 
  char ch,infile[10],outfile[10];
  printf("输入读入文件的名字:");
  scanf("%s",infile);
  printf("输入输出文件的名字:");
  scanf("%s",outfile);
  if((in=fopen(infile,"w"))==NULL)
  {
  printf("无法打开文件\n");
  exit(0);
  }//打开文件1,判断是否有错误 
  if((out=fopen(outfile,"w"))==NULL)
  {
  printf("无法打开文件\n");
  exit(0);
  }//打开文件2,判断是否有错误 
  while (!feof(in))//feof是检查所指向的是否结束 
  {
  ch=fgetc(in);
  fputc(ch,out);
  putchar(ch);
  }
  putchar(10);
  fclose(in);
  fclose(out);
  return 0;
}


这里面函数是feof函数。

他是用来判断所指向的文件是否结束;他是怎么判断一个文件是否结束的呢;

在访问磁盘文件时候,为了知道访问到了第几个字节的时候,系统用文件“文件读写位置标记”来表示访问的位置,当访问下一个字节时候,标记也会到下一个。所以说判断一个文件是否访问完成,可以根据他的访问位置是否在文件的末尾。


feof(in);结束:1;没有结束:0;


10.3.2 怎么向文件读写一个字符串

1670500585436.jpg


函数定义:char *fgets (char *str,int n,FILE*fp);指针函数,返回的是地址。
调用函数:fgets(str,n,fp);
定义了一个数组,其中包含n个元素,最后是字符串结束标志“\0”,所以说真正读入文件的字符串共包含n-1个字符。
为什么用char :???返回值是字符型的数据,
函数定义:int fputs(char*str,FILE*fp);定义一个整形函数,返回值是整型
调用函数:fputs("china",fp);括号内第一个位置可以是字符串常量,字符数组名,字符型指针;数组里的\0不输出到文件中。


看一个例子,从键盘读入若干个字符串,对他们按照字母大小的顺序排序,

然后把排序好的字符串送到磁盘的文件中保存

/*从键盘读入若干个字符串,对他们按照字母大小的顺序排序,
 然后把排序好的字符串送到磁盘的文件中保存*/ 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 int main()
 {
  FILE *fp;
  char  str[3][10],temp[10];
  int i,j,k,n=3;
  printf("ENTER strings:\n");
  //字符串赋值
  for(i=0;i<n;i++)
    gets(str[i]);//输入一个字符串给数组 同时顺便返回一个函数值;而该函数值就是这个数组的地址;str[i]是第一行的地址。
  //开始选择法排序
  for(i=0;i<n-1;i++)//循环一次 循环二次
  {
    k=i;
    for(j=i+1;j<n;j++)//循环两次  循环一次
    if(strcmp(str[k],str[j])>0) k=j;//比较字符串,找出最小的那个字符串的标记给K; 
    if(k!=i)//字符串互换 
    {
    strcmp(temp,str[i]);
    strcpy(str[i],str[k]);
    strcpy(str[k],temp);
   }
     }
     //打开了一个文件
  if((fp=fopen("D:\\CC\\wdw.dat","w"))==NULL)
  {
  printf("can't open file !\n");
  exit(0);
  } 
  //输出字符串
  printf("\nthe new sequence :\n ");
  for(i=0;i<n;i++)
  {
  fputs(str[i],fp);
  fputs("\n",fp);
  printf("%s\n",str[i]);
  }
  return 0;
}
fp=fopen("D:\\CC\\wdw.dat","w")
去指定目录下打开一个文件,写入数据;其实本来因改写成
fp=fopen("D:\CC\wdw.dat","w");这是正常的文件路径
但是\在C语言中包含转义的意思,所以为了避免重复,就用\\代替。

现在说怎么把这个字符串读出。

/*从键盘读入若干个字符串,对他们按照字母大小的顺序排序,
 然后把排序好的字符串送到磁盘的文件中保存,现在读出它*/ 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 int main()
 {
  FILE *fp;
  char  str[3][10];
  int i=0;    
     //打开了一个文件
  if((fp=fopen("Dstring.dat","r"))==NULL)
  {
  printf("can't open file !\n");
  exit(0);
  } 
  //输出字符串
  while(fgets(str[i],10,fp)!=NULL)
  {
  printf("%s",str[i]);
  i++;
  }
  fclose(fp);
  return 0;
}


本书是谭浩强的书,他在书中使用的是visual c++的环境编译;

我用的是dev c++和sublime txt 无法实现指定路径的写入。这个问题先留着

—————2020-1-1留;


10.3.3 用格式化的方式的读写文件


输入输出函数,如果是以终端为对象进行输入输出;(什么是终端,目前你理解为exe的执行窗口。)

printf();输出函数,从变量输出到终端;
scanf();输入函数,从终端输入到变量;


如果是以文件为对象,那么就不能使用以上的函数了;需要改为:

fprintf(文件指针,格式字符串,输出表列);
fprintf(fp,"%d,%6.2f",i,f);从变量输出到文件记事本中
fscanf(文件变量,格式字符串,输入表列);
fscanf(fp,"%d,%f",&i,&f);从文件记事本中输入到变量中


文件是在磁盘中,变量是在内存里,他们之间只能通过二进制来转化。

输入时要将文件中的ascall码转换成二进制形式再保存在内存变量中,在输出的时候又要将内存中的二进制形式转换成字符。

这样实现了以文件为终端的输入输出,但是耗时比较多。


10.3.4用二进制向文件读写一组数据


那咱们不转化,直接针对二进制文件,对于某种二进制文件往往比较大,也就是说文件的数据比较多。就是将内存的二进制的数据块直接搬运到磁盘。将磁盘的二进制数据块直接搬运到内存中;这种以文件为对象的输入输出函数:

fread(buffer,size,count,fp);从文件读出,保存到内存。
 buffer:是一个地址。存放数据的(内存中的)存储区的地址
 size:要读写的字节数
 count:要读写多少个数据项(每个数据项长度为size)
 fp:文件的指针
fwrite(buffer,size,count,fp);从内存读出,写入文件
 buffer:是一个地址。将(内存中的)存储区的数据输出到文件,内存存储区地址。
 size:要读写的字节数
 count:要读写多少个数据项(每个数据项长度为size)
 fp:文件的指针


fread fwrite 函数执行成功 返回count的数值。是个整数。


咱们看一个例子,来看一看怎么使用这个函数:

/*从键盘输入10个学生的有关数据,然后把他们转存到磁盘文件上去。*/
#include <stdio.h>
#define SIZE 10
//定义一个结构体数组包含是个学生的数据
struct student_type
{
   char name[10];
   int num;
   int age;
   char addr[15];
}stud[SIZE];
//将10个同学的数据从内存中读取出来,然后就是输出到磁盘中
void save()
{
   FILE *fp;
   int i;
   //打开文件,这个文件在磁盘中
   if((fp=fopen("stu.dat","wb"))==NULL)//用“wb”写入文件中
   {
    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);
}
//主函数,将数据填入,并且执行
int main()
{
   int i;
   printf("please erter data of students:\n");
   for (int i = 0; i < SIZE; i++)
   {
    scanf("%s%d%d%s",stud[i].name,&stud[i].num,&stud[i].age,stud[i].addr);
    save();
    return 0;
   }
}


这是从内存读出,写入文件的案例

那我同样把这段文件的二进制数据从文件中读出,写到内存中。

/*从键盘输入10个学生的有关数据,然后把他们转存到磁盘文件上去。*/
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
//定义结构体数组,包含十个数据
struct student_type
{
   char name[10];
   int num;
   int age;
   char addr[15];
}stud[SIZE];
定义指针变量,打开的文件指向指针变量,用fread 读写
int main()
{
   int i;
   FILE *fp;
   if((fp=fopen("stu.dat","rb"))==NULL)
   {
    printf("cannot open file\n");
    exit(0) ;
   }
   for(i=0;i<SIZE;i++)
   {
    fread(&stud[i],sizeof(struct student_type),1,fp);
    printf("%-10s %4d %4d %-15s",stud[i].name,stud[i].num,stud[i].age,stud[i].addr);
   }
   fclose(fp);
   return 0;
   }
}


注意:(??)

之前说了,在文件与内存之间。文件是在磁盘中,磁盘是在外存中。所以文件的数据换到内存中的时候,其中换行符和回车统统转换成换行符。就是说你代码上写一串换行符号,exe执行文件显示换行,你在exe文件敲打一个回车,同样是换行,就是说,数据从文件到内存,换行符和回车都被转换成换行。

从内存读出的时候,不发生字符转换。他也没有回车,只有换行符号。

咱们敲打的字写exe文件中的数据是在哪儿。送到内存的缓冲区。就相当于输入数据到内存。这是手动敲打。从文件读入也是输入数据的一种方式。都是一样的。都属于输送数据。


总结


就是输送数据:

1.exe上直接敲;手动输入数据

2.直接读文件数据;自动读入数据。

他们输入到内存都要转换。因为只有换行符号有对应的二进制代码。


这样理解可能是错的,读者这段独白属于在目前知识体系下的理解。仅供参考


相关文章
|
7月前
|
Java
Scanner与System.out为什么慢,快速输入输出模版,目录牛客.dd爱框框快速输入的代码快速输入输出快的原因 AC代码
Scanner与System.out为什么慢,快速输入输出模版,目录牛客.dd爱框框快速输入的代码快速输入输出快的原因 AC代码
|
8月前
|
XML 存储 Java
【OpenCV】—输入输出XML和YAML文件
【OpenCV】—输入输出XML和YAML文件
214 1
|
存储 C语言 索引
ENVI IDL:熟悉IDL语法+输出多幅TIFF影像的MAX文件和MEAN文件
ENVI IDL:熟悉IDL语法+输出多幅TIFF影像的MAX文件和MEAN文件
329 0
|
8月前
MFC编程 -- 读取文件内容
MFC编程 -- 读取文件内容
112 0
|
C++
C++分文件编写:拆类(.h和.cpp文件)
C++分文件编写:拆类(.h和.cpp文件)
146 0
ENVI_IDL:(批量处理)如何对HDF5文件进行GLT文件的创建并进行几何校正最终输出为IMG格式?
ENVI_IDL:(批量处理)如何对HDF5文件进行GLT文件的创建并进行几何校正最终输出为IMG格式?
196 0
|
存储 编解码
ENVI_IDL:读取OMI数据(HDF5)并输出为Geotiff文件+详细解析
ENVI_IDL:读取OMI数据(HDF5)并输出为Geotiff文件+详细解析
452 1
|
存储 编解码 Python
ENVI_IDL:对于书写和创建GEOTIFF结构体?
ENVI_IDL:对于书写和创建GEOTIFF结构体?
162 0
|
XML IDE 编译器
第一个excel VBA demo —— 添加信号并生成一段Verilog代码
第一个excel VBA demo —— 添加信号并生成一段Verilog代码
198 0
第一个excel VBA demo —— 添加信号并生成一段Verilog代码

热门文章

最新文章