C语言文件学习

——一般来说,文件是指一组相关数据的有序集合。文件通常是驻留在外部介质(如磁盘)上的,在使用时才调入内存。程序执行时,所有的数据都存储在内存中,这些数据只能临时存放而不能永久保存,要想永久保存就要把数据以文件形式存储在外存储器中。每个文件都有一个名字,操作系统以文件为单位对数据进行管理。

C语言从不同的角度对文件进行分类:

①从用户的角度,文件可分为普通文件和设备文件。

      普通文件是保存在磁盘或其他外部介质上的一个有序数据集。源文件、目标文件、可执行文件等都是普通文件。

      设备文件是指显示器、打印机、键盘等外部设备。C语言把外部设备也看作是一个文件来进行管理,把其输入、输出等同于对磁盘文件的读和写。例如:键盘被默认为标准输入文件,屏幕被默认为标准输出文件。

②根据数据的编码方式,可分为文本文件和二进制文件。

    文本文件是按照数据在内存中的存储形式放到磁盘上的。例如,整数12345678存储时被视为‘1’、‘2’、...‘8’,8个字符占8个字节。

       二进制文件是按照数据在内存中的存储形式放到磁盘上的。例如,整数12345678,在内存中按二进制形式存放,占4个字节。

                                                                           二进制VS文本

文件类型 文件优点 文件劣势
二进制 程序读写快

人类读写困难,而且不跨平台

int(数据类型)大小不一致,大小端问题

文本 便于人类读写,而且跨平台 程序输入输出需要格式化,开销大

目前C语言使用的文件系统分为缓冲文件系统(标准I/O)和非缓冲文件系统(系统I/O)。

  ←缓冲文件系统

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

int main(){

FILE *fp;
fp=fopen("f1.txt","w");
fprintf(fp,"Hello World!");
fclose(fp);
return 0;
}

*fp是文件指针;每一个被使用的文件都要在内存中开辟一个区域,用来存放有关信息,包括文件名称、文件状态和文件当前位置等。这些信息被保存在一个结构变量中,该结构类型被系统定义为FILE,放在“stdio.h”FILE的结构大致是这样:

typedef struct
{
    short level;/*缓冲区使用量*/
    unsigned flags; /*文件状态标志*/
    char fd;      /*文件描述符*/
    short bsize;   /*缓冲区大小*/
    unsigned char *buffer;/*文件缓冲区的首地址*/
    unsigned char *curp;/*指向文件缓冲区的工作指针*/
    unsigned char hold;/*其他信息*/
    unsigned istemp;
    short token;
}FILE;

fopen函数用来打开一个文件,其调用的一般形式为:

文件指针名  =  fopen(文件名字符串,使用文件方式字符串);

fp=fopen("f1.txt","w");

f1.txt默认在c工程所在的文件夹中。“w”表示建立只写文件,如果不存在新建一个并写入,若存在,直接写入覆盖文件原来内容。


输入/输出重定向函数freopen()

freopen("in.txt","r",stdin);

把标准输入流stdin重定向到in.txt中,在scanf的时候,不在从键盘输入文件中读取,而是从in.txt文件中读取。

freopen("out.txt","w",stdout);

把可执行程序的标准输出或标准错误输出重新定向到指定的out.txt文件中。把stdout重定向到out.txt中,输出结果不会显示到标准输出设备上,而是保存到out.txt中。

重定向文件算a+b,结果保存在out.txt文件中:

int main(){
int a,b;
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
while(scanf("%d%d",&a,&b)!=EOF){
    printf("%d\n",a+b);
}
fclose(stdin);
fclose(stdout);
return 0;
}

字符读/写函数fgetc()和fputc()

①fputc函数是将一个字符写到磁盘文件中,同时移动读写位置指针到下一个写入位置。

fputc(字符型变量,文件指针);

如果写入成功,返回该字符,失败,返回EOF(-1)

②fgetc函数从磁盘中读取一个字符,无出错返回值。

fgetc(文件指针);

int main(){
FILE *fp;
char ch;
if(!(fp=fopen("f2.txt","w")))
{
    printf("can not open this file\n");
    return;//exit(0)
}
for(;(ch=getchar())!='@';)
    fputc(ch,fp);

    fclose(fp);

if(!(fp=fopen("f2.txt","r")))
{
    printf("can not open this file\n");
    return;//exit(0)
}
for(;(ch=fgetc(fp))!=EOF;)
    putchar(ch);

    fclose(fp);
return 0;
}

字符串读/写函数fgets()和fputs()

①fputs函数用来向指定的文件写入一个字符串

fputs(字符数组,文件指针);

其中字符数组要写入的字符串,可以是一个字符串常量、或字符指针变量名。需要注意的是结束符'\0'不写入文件,若写成功,返回一个非负数;否则,返回EOF。

②fgets函数从文件中读取字符串,成功,返回字符串,失败,返回空指针

fgets(字符数组,字符个数(字符串长度),文件指针);字符串长度如果用strlen函数,需要加一,即strlen(string)+1,因为strlen是不统计'\0'的,用sizeof(string)不用加一。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LEN 100
int main(){
FILE *fp;
char string[LEN];
if(!(fp=fopen("f2.txt","w")))
{
    printf("can not open this file\n");
    return;//exit(0)
}
printf("Input a string:");
gets(string);
fputs(string,fp);
fclose(fp);
if(!(fp=fopen("f2.txt","r")))
{
    printf("can not open this file\n");
    return;//exit(0)
}
fgets(string,sizeof(string),fp);
printf("Output the string:");
puts(string);
fclose(fp);
return 0;
}

格式化文件读/写函数fscanf()和fprintf()

fscanf(文件指针,格式字符串,输入表);

fprintf(文件指针,格式字符串,输出表);

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LEN 100
struct hero{
    char name[10],petname[10],id[12];
    int age;
}Hero[LEN];
int main(){
FILE *fp,*fp1;
int i,count=0;

fp=fopen("f1.txt","r");
if(fp==NULL){
    printf("Can not read data from file f1!\n");
    return;
}

fp1=fopen("f2.txt","w");
if(fp1==NULL){
    printf("can not write data to file f2!\n");
    return;
}
for(i=0;(fscanf(fp,"%s%s%d%s",Hero[i].name,Hero[i].petname,&Hero[i].age,Hero[i].id))!=EOF;i++){count++;}
for(i=0;i<count;i++)
{
    fprintf(fp1,"%s %s %d %s\n",Hero[i].name,Hero[i].petname,Hero[i].age,Hero[i].id);
}

for(i=0;i<count;i++){
    printf("%s %s %d %s\n",Hero[i].name,Hero[i].petname,Hero[i].age,Hero[i].id);
}
fclose(fp);
fclose(fp1);
return 0;
}

数据块读/写函数fread()和fwrite()

fread(数据区首地址,每次读取的字节数,读取次数,文件指针);

fwrite(数据区首地址,每次写入的字节数,写入次数,文件指针);

数据存储区首地址可以是数组名、结构变量或结构指针。如果操作成功,返回1;失败,返回0。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LEN 100
struct hero{
    char name[10];
    char petname[10];
    int age;
    char id[12];
}Hero[LEN];
int main(){
FILE *fp,*fp1;
int i,count=0;

fp=fopen("f1.txt","r");
if(fp==NULL){
    printf("Can not read data from file f1!\n");
    return;
}

fp1=fopen("f2.txt","w");
if(fp1==NULL){
    printf("can not write data to file f2!\n");
    return;
}

fread(Hero,sizeof(Hero[0]),4,fp);
fwrite(Hero,sizeof(Hero[0]),4,fp1);

fclose(fp);
fclose(fp1);
return 0;
}

fseek(文件指针,字节单位(整数),开始位置);

int main(){
FILE *fp,*fp1;
char t[20];
char s[]="How are you!";
if((fp=fopen("f1.txt","w"))==0){
    printf("File open error!\n");
    return;
}
fwrite(s,strlen(s),1,fp);
fclose(fp);
if((fp1=fopen("f1.txt","r"))==0){
    printf("File open error!\n");
    return;
}
fseek(fp1,3,0);
fread(t,7,1,fp1);
t[7]='\0';
printf("\n%s\n",t);
fclose(fp1);
return 0;
}
⭐其中,fp,fp1不能用一个,一个是写入的文件指针,一个是读出的文件指针,不然用一个的话,会输出不了正常的字符串。


猜你喜欢

转载自blog.csdn.net/xsgg1234/article/details/80079396
今日推荐