I/O -x 标准IO fopen-fclose--fgetc-fputc--fgets-fputs--fwrite-fread--fprintf-fscanf

  文件是程序设计中的一个重要概念。所谓“文件”一般是指存储在外部介质上数据的集合。一批文件是以数据的形式存放在外部介质(如磁盘)上的。操作系统是以文件为单位对数据进行管理的,也就是说,如果想找存在外部介质上的数据,必须先按文件名找到指定的文件,然后再从该文件中读取数据。要向外部介质上存储数据也必须先建立一个文件(以文件名标识),才能向它输出数据。

文件本质
  从操作系统的角度来看,每一个与主机相连的输出输入设备都看作是一个文件。
在程序运行时,常常需要将一些数据(运行的最终结果或中间数据)输出到磁盘上存放起来,以后需要时再从磁盘中输入到计算机的内存。这就要用到磁盘文件。

C语言将文件看作是一个字符(字节)的序列,即一个一个字符(字节)的数据顺序组成。根据数据的组成形式,可分为ASCII文件和二进制文件。
  ASCII文件又称文本(text)文件,它的每一个字节可放一个ASCII码,代表一个字符。
  二进制文件是把内存中的数据按其在内存中的存储形式按原样输出到磁盘上存放。
  因而一个C文件就是一个字节流或二进制流。它把数据看作是一连串的字符(字节),而不考虑记录的界限。换句话说,C语言中文件不是由记录(record)组成的(这是和PASCAL或其他高级语言不同的)。在C语言中对文件的存取是以字符(字节)为单位的。输出输入的数据流的开始和结束仅受程序控制而不受物理符号(如回车换行符)控制。也就是说,在输出时不会自动增加回车换行符作为记录结束的标志,输入时不以回车换行符作为记录的间隔(事实上C文件并不是由记录构成的)。把这种文件称为流式文件。C语言允许对文件存取一个字符,这就增加了处理的灵活性。

C文件规定
  在C语言中,没有输入输出语句,对文件的读写都是用库函数来实现的。ANSI规定了标准输入输出函数,用它们对文件进行读写。

C文件操作
  在C语言中,文件操作都是由库函数来完成的,下面就是一些常用操作及函数:

需要包含头文件:stdio.h



fopen:打开
  fopen函数用来打开一个文件,其调用的一般形式为:文件指针名=fopen(文件名,打开方式) 其中,例如:

FILE *fp;
fp=fopen("file.a","r");

  其意义是在当前目录下打开文件file a,只允许进行“读”操作,并使fp指向该文件。
打开方式主要有以下若干类:
  r:只读打开一个文本文件,只允许读数据
  w:只写打开或建立一个文本文件,只允许写数据
  a:追加打开一个文本文件,并在文件末尾写数据
  t:以文本的方式打开文件
  b:以二进制的方式打开文件
  +:可读可写
另外
  rt+:读写打开一个文本文件,允许读和写
  wt+:读写打开或建立一个文本文件,允许读写
  at+:读写打开一个文本文件,允许读,或在文件末追加数据
  rb+:读写打开一个二进制文件,允许读和写
  wb+:读写打开或建立一个二进制文件,允许读和写
  ab+:读写打开一个二进制文件,允许读,或在文件末追加数据
判断打开是否成功:

if((fp=fopen("c:\\hzk16","rb")==NULL)
{
printf("\nerror on open c:\\hzk16 file!");
exit(-1);
}

  

fclose:关闭文件
  调用的一般形式是: fclose(文件指针); 例如:

fclose(fp);

  正常完成关闭文件操作时,fclose函数返回值为0。如返回非零值则表示有错误发生。

fgetc:读字符(很少用)
  fgetc函数的功能是从指定的文件中读一个字符,函数调用的形式为:
    字符变量=fgetc(文件指针)

可参考下例:
[例10.1]读入文件e10-1.c,在屏幕上输出。

#include<stdio.h>
main()
{
FILE *fp;
char ch;
if((fp=fopen("e10_1.c","rt"))==NULL)
{
printf("Cannot open file strike any key exit!");
getch();
exit(1);
}
ch=fgetc(fp);
while (ch!=EOF)
{
putchar(ch);
ch=fgetc(fp);
}
fclose(fp);
}

fputc:向文件写字符(很少用)
  fputc函数的功能是把一个字符写入指定的文件中,函数调用的形式为: fputc(字符量,文件指针);
[例10.2]从键盘输入一行字符,写入一个文件, 再把该文件内容读出显示在屏幕上。
参考下例:

#include<stdio.h>
main()
{
FILE *fp;
char ch;
if((fp=fopen("string","wt+"))==NULL)
{
printf("Cannot open file strike any key exit!");
getch();
exit(1);
}
printf("input a string:\n");
ch=getchar();
while (ch!=‘\n‘)
{
fputc(ch,fp);
ch=getchar();
}
rewind(fp);
ch=fgetc(fp);
while(ch!=EOF)
{
putchar(ch);
ch=fgetc(fp);
}
printf("\n");
fclose(fp);
}

  

fgets:读取字符串

  从指定的文件中读一个字符串到字符数组中,函数调用的形式为:
     fgets(字符数组名,n,文件指针);
  n是一个正整数,表示从文件中读出的字符串不超过 n-1个字符。在读入的最后一个字符后加上串结束标志‘\0‘。
例如:fgets(str,n,fp);的意义是从fp所指的文件中读出n-1个字符送入字符数组str中。

[例10.4]从e10_1.c文件中读入一个含10个字符的字符串。

#include<stdio.h>
main()
{
FILE *fp;
char str[11];
if((fp=fopen("e10_1.c","rt"))==NULL)
{
printf("Cannot open file strike any key exit!");
getch();
exit(1);
}
fgets(str,11,fp);
printf("%s",str);
fclose(fp);
}

本例定义了一个字符数组str共11个字节,在以读文本文件方式打开文件e101.c后,从中读出10个字符送入str数组,在数组最后一个单元内将加上‘\0‘,然后在屏幕上显示输出str数组。输出的十个字符正是例10.1程序的前十个字符。
对fgets函数有两点说明:
1. 在读出n-1个字符之前,如遇到了换行符或EOF,则读出结束。
2. fgets函数也有返回值,其返回值是字符数组的首地址。

fputs:向文件写一个字符串
  puts函数的功能是向指定的文件写入一个字符串,其调用形式为: fputs(字符串,文件指针) 其中字符串可以是字符串常量,也可以是字符数组名,或指针 变量,例如:

fputs(“abcd“,fp);

  其意义是把字符串“abcd”写入fp所指的文件之中。[例10.5]在例10.2中建立的文件string中追加一个字符串。

#include<stdio.h>
main()
{
FILE *fp;
char ch,st[20];
if((fp=fopen("string","at+"))==NULL)
{
printf("Cannot open file strike any key exit!");
getch();
exit(1);
}
printf("input a string:\n");
scanf("%s",st);
fputs(st,fp);
rewind(fp);
ch=fgetc(fp);
while(ch!=EOF)
{
putchar(ch);
ch=fgetc(fp);
}
printf("\n");
fclose(fp);
}

本例要求在string文件末加写字符串,因此,在程序第6行以追加读写文本文件的方式打开文件string 。 然后输入字符串, 并用fputs函数把该串写入文件string。在程序15行用rewind函数把文件内部位置指针移到文件首。 再进入循环逐个显示当前文件中的全部内容。

fread/fwrite:文件块读写(二进制读写利器) 

  C语言还提供了用于整块数据的读写函数。 可用来读写一组数据,如一个数组元素,一个结构变量的值等。
读数据块函数调用的一般形式为: fread(buffer,size,count,fp);
写数据块函数调用的一般形式为: fwrite(buffer,size,count,fp);
  其中buffer是一个指针,在fread函数中,它表示存放输入数据的首地址。在fwrite函数中,它表示存放输出数据的首地址。 size 表示数据块的字节数。count 表示要读写的数据块块数。fp 表示文件指针。

例如:
  fread(fa,4,5,fp); 其意义是从fp所指的文件中,每次读4个字节(一个实数)送入实数组fa中,连续读5次,即读5个实数到fa中。
[例10.6]从键盘输入两个学生数据,写入一个文件中, 再读出这两个学生的数据显示在屏幕上。

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 struct stu
 4 {
 5 char name[10];
 6 int num;
 7 int age;
 8 char addr[15];
 9 }boya[2],boyb[2],*pp,*qq;
10
11 main()
12 {
13 FILE *fp;
14 char ch;
15 int i;
16 pp=boya;
17 qq=boyb;
18
19 if((fp=fopen("stu_list","wb+"))==NULL)
20 {
21 printf("Cannot open file strike any key exit!");
22 getchar();
23 exit(1);
24 }
25
26 printf("\ninput data\n");
27 for(i=0;i<2;i++,pp++)
28     scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);
29 pp=boya;
30 fwrite(pp,sizeof(struct stu),2,fp);
31 rewind(fp);
32
33 fread(qq,sizeof(struct stu),2,fp);
34 printf("\n\nname\tnumber age addr\n");
35 for(i=0;i<2;i++,qq++)
36     printf("%s\t%5d%7d%s\n",qq->name,qq->num,qq->age,qq->addr);
37 fclose(fp);
38 }

  本例程序定义了一个结构stu,说明了两个结构数组boya和 boyb以及两个结构指针变量pp和qq。pp指向boya,qq指向boyb。程序第16行以读写方式打开二进制文件“stu_list”,输入二个学生数据之后,写入该文件中, 然后把文件内部位置指针移到文件首,读出两块学生数据后,在屏幕上显示。

fscanf/fprintf:格式化读写函数

  fscanf函数,fprintf函数与前面使用的scanf和printf 函数的功能相似,都是格式化读写函数。两者的区别在于 fscanf 函数和fprintf函数的读写对象不是键盘和显示器,而是磁盘文件。
    这两个函数的调用格式为:fscanf(文件指针,格式字符串,输入表列); fprintf(文件指针,格式字符串,输出表列);
例如:

  fscanf(fp,"%d%s",&i,s);
  fprintf(fp,"%d%c",j,ch);
用fscanf和fprintf函数也可以完成例10.6的问题。修改后的程序如例10.7所示。
[例10.7]

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 struct stu
 4 {
 5 char name[10];
 6 int num;
 7 int age;
 8 char addr[15];
 9 }boya[2],boyb[2],*pp,*qq;
10
11 main()
12 {
13 FILE *fp;
14 char ch;
15 int i;
16 pp=boya;
17 qq=boyb;
18 if((fp=fopen("stu_list","wb+"))==NULL)
19 {
20 printf("Cannot open file strike any key exit!");
21 getchar();
22 exit(1);
23 }
24 printf("\ninput data\n");
25 for(i=0;i<2;i++,pp++)
26   scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);
27 pp=boya;
28 for(i=0;i<2;i++,pp++)
29   fprintf(fp,"%s %d %d %s\n",pp->name,pp->num,pp->age,pp->addr);
30 rewind(fp);
31 for(i=0;i<2;i++,qq++)
32   fscanf(fp,"%s %d %d %s\n",qq->name,&qq->num,&qq->age,qq->addr);
33 printf("\n\nname\tnumber age addr\n");
34 qq=boyb;
35 for(i=0;i<2;i++,qq++)
36   printf("%s\t%5d %7d %s\n",qq->name,qq->num, qq->age,
37 qq->addr);
38 fclose(fp);
39 }

与例10.6相比,本程序中fscanf和fprintf函数每次只能读写一个结构数组元素,因此采用了循环语句来读写全部数组元素。

还要注意指针变量pp,qq由于循环改变了它们的值,因此在程序的25和32行分别对它们重新赋予了数组的首地址。

时间: 2024-11-07 13:29:23

I/O -x 标准IO fopen-fclose--fgetc-fputc--fgets-fputs--fwrite-fread--fprintf-fscanf的相关文章

文件流:&quot;fopen&quot;,&quot;fclose&quot;,“ftell”&quot;fseek&quot;,&quot;fgets&quot;,&quot;fprintf&quot; ,“feof”,&quot;fwrite&quot;,&quot;fread&quot;

char const* filename="D:/hello.txt"; "fopen", FILE *fp=fopen(char const *name,char const mode); e.g:FILE *fp = fopen(filename,"wb"); 打开文件流,name为要打开文件的路径,如这里的filename:mode 为对文件的操作模式,通常使用:"wb"(写操作),"rb"(读操作)

第一天20150829:标准IO 和 系统IO -----stdio and sysio

IO 的实现包括两种实现: 1.stdio标准IO 2.sysio系统IO IO的两种实现方式正常都可以使用.但是,在使用的过程中优先使用stdio标准IO. 首先要了解这两种实现的原理: 1.sysio系统IO:我们作为USER 要与内核对话,那么系统为我们提供了一个sysio,可以直接对话KERNAL. 那么问题就产生了:如果USER使用的平台环境不一样(有的人有linux,有的人用windows),那么由于KERNAL不一样,那么提供给USER的sysio也会不一样 2.所以引申出来一个标

内核IO和标准IO

对于文件的读写操作函数在执行的空间来分,可以分为内核IO(主要在内核中运行)和标准IO(主要在用户空间中运行). 内核IO需要自己创建和管理缓存,而标准IO是自动分类缓存,一般来说,内核IO的效率高于标准IO,但是差距不是很大,考虑移植性,还是建议使用标准IO(只要是支持标准C语言就支持标准IO). 无论是标准IO还是内核IO都是对文件的信息,读写文件的指针进行记录的,调用相应的函数可以进行文件信息的读取和指针的修改. 以下为IO相关的函数的头文件,使用,参数,返回值的说明 linux C语言I

标准IO与文件IO 的区别【转】

本文转载自:http://blog.sina.com.cn/s/blog_63f31f3401013jrn.html 先来了解下什么是标准IO以及文件IO. 标准IO:标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具有一定的可移植性.标准IO库处理很多细节.例如缓存分配,以优化长度执行IO等.标准的IO提供了三种类型的缓存. (1)全缓存:当填满标准IO缓存后才进行实际的IO操作.         (2)行缓存:当输入或输出中遇到新行符时,标准

标准IO与文件IO 的区别

1.定义 标准IO:标准I/O是ANSI C建立的一个标准I/O模型,是一个标 准函数包和stdio.h头中的定义,具有一定的可移植性.标准IO库处理很多细节.例如缓存分配,以优化长度执行IO等.标准的IO提供了三种类型的缓存.(1)全缓存:当填满标准IO缓存后才进行实际的IO操作.(2)行缓存:当输入或输出中遇到新行符时,标准IO库执行IO操作.(3)不带缓存:stderr就是了. 文件IO:文件IO称之为不带缓存的IO(unbuffered I/O).不带缓存指的是每个read,write都

文件IO和标准IO

2015.2.26 星期四,阴天 今天的内容主要是文件IO man 手册的分册: man -f open 查看那些分册中有openman 1 -- 普通的命令程序man 2 -- 系统调用man 3 -- 库函数 文件:操作系统将硬件抽象成文件输入:将设备中的数据写进到内存输出:将内存中的数据写出到设备 Linux的文件系统由两层结构构成:第一层是虚拟文件系统(VFS),第二层是各种不同的具体的文件系统 posix:可移植操作系统接口规范API:用户编程接口 应用通过POSIX和GNU C LI

标准IO

标准IO由ISO C 标准的IO库,它处理了很多底层细节,比如合适的缓冲大小等等,因此更易于使用,但是也引入了一些其他问题. 流向 标准IO使用FILE对象关联流,流可以是面向宽字节的也可以是面向单字节的,当流初始化的时候是没有方向的,如果后面的IO操作是处理的宽字符集的,流变成面向宽字节的,如果哦是处理单字节的,流变成面向单字节,一旦流有了方向,不可改变,直到流被关闭,fwide可以设置流的方向,freopen可以清楚流的方向. #include <wchar.h> int fwide(FI

读书笔记-APUE第三版-(5)标准IO库

ISO C标准I/O库使用流的概念读写文件.流是对数据传输的抽象,可以把流理解为从起点到终点间的字节序列. 标准I/O库通过维护进程空间内的缓冲区,减少read/write系统调用次数来提高I/O效率.之前介绍的Unbuffered I/O和文件描述符fd打交道,标准I/O则使用FILE指针. typedef struct{ short level;/*缓冲区满程度*/ unsigned flags;/*文件打开状态标志*/ char fd;/*文件描述符*/ unsigned char hol

Unix环境之标准IO库

UNIX的文件IO都是针对文件描述符的,而标准IO的操作则是围绕流进行的.当一个流最初被创建时,它并没有定向.若在未定向的流上使用一个多字节IO函数,则将该流的定向设置为宽定向:若在未定向的流上使用一个单字节IO函数,则将该流的定向设置为字节定向. stdio.h定义了三个标准流,stdin.stdout和stderr,分别是标准输入.标准输出和标准出错. 缓冲-- 标准IO库提供缓冲的目的是尽可能减少使用read和write调用的次数.它也对每个IO流自动地进行缓冲管理,从而避免了应用程序需要

Unix高级编程之标准IO

c标准io---带缓存的io 优势: 带缓存(合并系统调用)缺点: 实时性低缓存的类型: 行缓存:stdin stdout(缓存区是有大小) 全缓存:文件 无缓存:stderr 1.流 打开文件的标识 2.FILE类型 结构体类型: 文件描述符 缓存区的地址 缓存的大小 出错标识 3.流的打开 fopen(3); errno全局变量 定义的宏: /usr/include/asm-generic/errno-base.h /usr/include/asm-generic/errno.h strer