文件是数据源的一种,最主要的作用是保存数据。在操作系统中,为了统一对各种硬件的操作,简化接口,不同的硬件设备也都被看成一个文件。例如显示器为标准输出文件,printf就是向这个文件输出数据;键盘为标准输入文件,scanf就是从这个文件读取数据。 操作文件的正确流程为:打开文件-->读写文件-->关闭文件。文件在进行读写操作之前要先打开,使用完毕之后要关闭。
我们把数据在数据源和内存之间传递的过程叫做数据流,相应的,数据从数据源到内存的过程叫做输入流,从内存到数据源的过程叫做输出流。数据在文件和内存之间传递的过程叫做文件流。
不同的操作需要不同的文件权限。例如,只想读取文件中的数据的话,只读权限就够了;既想读取又想写入数据的话,读写权限就是必须的。另外,文件也有不同的类型,按照数据的存储方式可以分为二进制文件和文本文件,它们的操作细节是不同的。 整体来说,文件打开方式由 r、w、a、t、b、+ 六个字符拼成,各字符的含义如下:
以字符形式读写文件时,每次可以从文件中读取一个字符,或者向文件中写入一个字符。主要使用两个函数,分别是fgetc()和fputc()。
EOF是end of file的缩写,表示文件末尾,是在stdio.h中定义的宏,它的值是一个负数,往往是-1。EOF不绝对是-1,也可以是其他负数,这要看编译器的实现。EOF本来表示文件末尾,意味着读取结束,但是很多函数在读取出错时也返回EOF,我们可以借助stdio.h中的两个函数来判断,分别是feof()和ferror()。
fgetc()和fputc()函数每次只能读写一个字符,速度较慢,实际开发中往往是每次读写一个字符串或者一个数据块,这样能明显提高效率。fgets()函数用来从指定的文件中读取一个字符串,并保存到字符数组中;fputs()函数用来向指定的文件写入一个字符串。
需要注意的是,读取到的字符串会在末尾自动添加'\0',n个字符也包括'\0'。也就是说,实际只读取到了n-1个字符,如果希望读取100个字符,n的值应该为101。另外,在读取到n-1个字符之前如果出现了换行,或者读到了文件末尾,则读取结束。这就意味着,不管n的值多大,fgets()最多只能读取一行数据,不能跨行。在C语言中,没有按行读取文件的函数,我们可以借助fgets(),将n的值设置的足够大,每次就可以读取到一行数据。
如果希望读取多行内容,需要使用fread()函数,相应地写入函数为fwrite()。对于Windows系统,使用fread()和fwrite()时应该以二进制的形式打开文件。
返回成功读写的块数count,如果返回值小于count:
示例:从键盘输入两个学生数据,写入一个文件中,再读出这两个学生的数据显示在屏幕上。
fscanf()和fprintf()函数与前面使用的scanf()和printf()功能相似,都是格式化读写函数,两者的区别在于fscanf()和fprintf()的读写对象不是键盘和显示器,而是磁盘文件。 示例:用 fscanf 和 fprintf 函数来完成对学生信息的读写。
实际开发中经常需要读写文件的中间部分,要解决这个问题,就得先移动文件内部的位置指针,再进行读写。这种读写方式称为随机读写,实现随机读写的关键是要按要求移动位置指针,这称为文件的定位。
参数说明:
示例:从键盘输入三组学生信息,保存到文件中,然后读取第二个学生的信息。
/
*
函数功能:打开文件
参数一:文件名
参数二:文件打开方式
返回值:
FILE
结构体,保存了文件名、文件状态、当前读写位置等。
*
/
FILE
*
fopen(char
*
filename,char
*
mode);
/
*
函数功能:关闭文件
参数一:文件指针
返回值:正常关闭文件返回零,错误返回非零值。
*
/
int
fclose(
FILE
*
fp)
/
*
函数功能:打开文件
参数一:文件名
参数二:文件打开方式
返回值:
FILE
结构体,保存了文件名、文件状态、当前读写位置等。
*
/
FILE
*
fopen(char
*
filename,char
*
mode);
/
*
函数功能:关闭文件
参数一:文件指针
返回值:正常关闭文件返回零,错误返回非零值。
*
/
int
fclose(
FILE
*
fp)
int
main()
{
FILE
*
fp;
char ch;
/
/
如果文件不存在,给出提示并退出
if
((fp
=
fopen(
"D:\\demo.txt"
,
"rt"
))
=
=
NULL)
{
puts(
"Fail to open file!"
);
exit(
0
);
}
/
/
每次读取一个字节,直到读取完毕
while
((ch
=
fgetc(fp)) !
=
EOF)
{
putchar(ch);
}
/
/
输出换行符
putchar(
'\n'
);
if
(ferror(fp))
{
puts(
"读取出错"
);
}
else
{
puts(
"读取成功"
);
}
fclose(fp);
return
0
;
}
int
main()
{
FILE
*
fp;
char ch;
/
/
如果文件不存在,给出提示并退出
if
((fp
=
fopen(
"D:\\demo.txt"
,
"rt"
))
=
=
NULL)
{
puts(
"Fail to open file!"
);
exit(
0
);
}
/
/
每次读取一个字节,直到读取完毕
while
((ch
=
fgetc(fp)) !
=
EOF)
{
putchar(ch);
}
/
/
输出换行符
putchar(
'\n'
);
if
(ferror(fp))
{
puts(
"读取出错"
);
}
else
{
puts(
"读取成功"
);
}
fclose(fp);
return
0
;
}
int
main()
{
FILE
*
fp;
char ch;
/
/
判断文件是否成功打开
if
((fp
=
fopen(
"D:\\demo.txt"
,
"wt+"
))
=
=
NULL)
{
puts(
"Fail to open file!"
);
exit(
0
);
}
printf(
"Input a string:\n"
);
/
/
每次从键盘读取一个字符并写入文件
while
((ch
=
getchar()) !
=
'\n'
)
{
fputc(ch,fp);
}
fclose(fp);
return
0
;
}
int
main()
{
FILE
*
fp;
char ch;
/
/
判断文件是否成功打开
if
((fp
=
fopen(
"D:\\demo.txt"
,
"wt+"
))
=
=
NULL)
{
puts(
"Fail to open file!"
);
exit(
0
);
}
printf(
"Input a string:\n"
);
/
/
每次从键盘读取一个字符并写入文件
while
((ch
=
getchar()) !
=
'\n'
)
{
fputc(ch,fp);
}
fclose(fp);
return
0
;
}
/
*
判断文件操作是否出错,出错时返回非零值,否则返回零值。
*
/
int
ferror (
FILE
*
fp);
/
*
判断文件内部指针是否指向了文件末尾,
当指向文件末尾时返回非零值,否则返回零值
*
/
int
feof (
FILE
*
fp);
/
*
判断文件操作是否出错,出错时返回非零值,否则返回零值。
*
/
int
ferror (
FILE
*
fp);
/
*
判断文件内部指针是否指向了文件末尾,
当指向文件末尾时返回非零值,否则返回零值
*
/
int
feof (
FILE
*
fp);
int
main()
{
FILE
*
fp;
char
str
[N
+
1
];
if
((fp
=
fopen(
"d:\\demo.txt"
,
"rt"
))
=
=
NULL)
{
puts(
"Fail to open file!"
);
exit(
0
);
}
while
(fgets(
str
, N, fp) !
=
NULL)
{
printf(
"%s"
,
str
);
}
fclose(fp);
return
0
;
}
int
main()
{
FILE
*
fp;
char
str
[N
+
1
];
if
((fp
=
fopen(
"d:\\demo.txt"
,
"rt"
))
=
=
NULL)
{
puts(
"Fail to open file!"
);
exit(
0
);
}
while
(fgets(
str
, N, fp) !
=
NULL)
{
printf(
"%s"
,
str
);
}
fclose(fp);
return
0
;
}
int
main()
{
FILE
*
fp;
char
str
[
102
]
=
{
0
}, strTemp[
100
];
if
((fp
=
fopen(
"D:\\demo.txt"
,
"at+"
))
=
=
NULL)
{
puts(
"Fail to open file!"
);
exit(
0
);
}
printf(
"Input a string:"
);
gets(strTemp);
strcat(
str
,
"\n"
);
strcat(
str
, strTemp);
fputs(
str
, fp);
fclose(fp);
return
0
;
}
int
main()
{
FILE
*
fp;
char
str
[
102
]
=
{
0
}, strTemp[
100
];
if
((fp
=
fopen(
"D:\\demo.txt"
,
"at+"
))
=
=
NULL)
{
puts(
"Fail to open file!"
);
exit(
0
);
}
printf(
"Input a string:"
);
gets(strTemp);
strcat(
str
,
"\n"
);
strcat(
str
, strTemp);
fputs(
str
, fp);
fclose(fp);
return
0
;
}
/
/
从指定文件中读取块数据
size_t fread(void
*
ptr,size_t size,size_t count,
FILE
*
fp);
/
/
向文件中写入块数据
size_t fwrite( void
*
ptr,size_t size,size_t count,
FILE
*
fp);
/
/
所谓块数据,也就是若干个字节的数据,可以是一个字符,可以是一个字符串,可以是多行数据,并没有什么限制。
/
/
从指定文件中读取块数据
size_t fread(void
*
ptr,size_t size,size_t count,
FILE
*
fp);
/
/
向文件中写入块数据
size_t fwrite( void
*
ptr,size_t size,size_t count,
FILE
*
fp);
/
/
所谓块数据,也就是若干个字节的数据,可以是一个字符,可以是一个字符串,可以是多行数据,并没有什么限制。
struct stu
{
char name[
10
];
/
/
姓名
int
num;
/
/
学号
int
age;
/
/
年龄
float
score;
/
/
成绩
}boya[N], boyb[N],
*
pa,
*
pb;
int
main()
{
FILE
*
fp;
int
i;
pa
=
boya;
pb
=
boyb;
if
((fp
=
fopen(
"d:\\demo.txt"
,
"wb+"
))
=
=
NULL)
{
puts(
"Fail to open file!"
);
exit(
0
);
}
/
/
从键盘输入数据
printf(
"Input data:\n"
);
for
(i
=
0
; i<N; i
+
+
,pa
+
+
)
{
scanf(
"%s %d %d %f"
,pa
-
>name,&pa
-
>num,&pa
-
>age,&pa
-
>score);
}
/
/
将数组 boya 的数据写入文件
fwrite(boya, sizeof(struct stu), N, fp);
/
/
将文件指针重置到文件开头
rewind(fp);
/
/
从文件读取数据并保存到数据 boyb
fread(boyb, sizeof(struct stu), N, fp);
/
/
输出数组 boyb 中的数据
for
(i
=
0
; i<N; i
+
+
,pb
+
+
)
{
printf(
"%s %d %d %f\n"
,pb
-
>name,pb
-
>num,pb
-
>age,pb
-
>score);
}
fclose(fp);
return
0
;
}
struct stu
{
char name[
10
];
/
/
姓名
int
num;
/
/
学号
int
age;
/
/
年龄
float
score;
/
/
成绩
}boya[N], boyb[N],
*
pa,
*
pb;
int
main()
{
FILE
*
fp;
int
i;
pa
=
boya;
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课