打开目的
|
ASCII
码文件
|
二进制
文件
|
备
注
|
只读(输入)
|
r
|
r
b
|
文件
已经存在
|
只写(输出)
|
w
|
w
b
|
有则删
无则建
|
向文件尾
追加数据
|
a
|
a
b
|
文件
已经存在
|
读/写文件
|
r+
/
a+
|
rb+
/
a
b
+
|
文件
已经存在
|
创建新文件
|
w+
|
w
b
+
|
有则删
无则建
|
int fopen(FILE *
文件指针
);
1
.用法:
FILE * fopen
("
文件名
"
,
"
操作方式
");
2
.功能:返回一个指向文件的指针。
3
.函数原型:
stdio.h
。
如果打开操作
失败
,则
fopen()
函数返回一个
空指针
NULL
(
其值在头文件stdio.h中被定义为0)
。
为增强程序可靠性,常用如下方法打开一个文件:
if( ( fp = fopen("
文件名
","
操作方式
") )==NULL)
{ printf("can not open this file/n");
exit(0);
}
int fclose(FILE *
文件指针
);
2
.功能:关闭
“
文件指针
”
所指向的文件。
3
.函数返回值:正常关闭,返回值为0;否则,返回值为非0。
例如,
fclose( fp )
;
/*
关闭
fp
所指向的文件
*/
另外:
写
1
个字符到文件中──
fputc()
函数
[
案例
]
从键盘上输入一个字符串(以
“@”
作为结束字符),以
ASCII
码形式存储到一个磁盘文件
diskfile.txt
中。
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
void main( )
{ FILE *fp;
char ch;
if ( ( fp = fopen("diskfile.txt", "w") )==NULL)
{ printf("can not open this file, press any key to exit......");
getch();
exit(0);
}
/*
输入字符,并存储到指定文件中
*/
for( ; ( ch = getchar() ) != '@' ; ) fputc( ch, fp );
fclose(fp);
}
int
fputc
(
字符数据
,
文件指针
);
(2)
功能:将字符数据写到指定文件中,并将
读
/
写位置指针
向前移动
1
个字节
(
即指向下一个写入位置)
。
(3)
返回值:
●
输出成功,返回输出的字符数据;
●
输出失败,返回一个符号常量
EOF
(
其值在头文件stdio.h中,被定义为-1)
。
从文件中读
1
个字符──
fgetc()
和
feof()
函数
[
案例
]
顺序显示创建的磁盘文件
diskfile.txt
。
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
void main( )
{ FILE *fp;
char ch;
if ( ( fp = fopen("diskfile.txt", "r") )==NULL)
{ printf("can not open source file, press any key to exit......");
getch();
exit(0);
}
for(; ( ch = fgetc(fp) ) != EOF; ) putchar( ch );
fclose(fp);
getch();
}
◆
符号常量
EOF
在对
ASCII
码文件
执行读入操作时,如果遇到文件尾,则返回一个文件结束标志
EOF
(
其值在头文件
stdio.h
中被定义为
-1)
。
int
feof
(
文件指针
) ;
(2)
功能:在执行
读
文件操作时,如果遇到
文件尾
,则函数返回逻辑
真
(1)
;否则,则返回逻辑
假
(0)
。
feof()
函数同时适用于
ASCII
码文件和
二进制文件
(
只能使用该函数,不能使用EOF)。
int
fgetc
(
文件指针
);
(2)
功能:从指定文件中读
1
个字符,并将读写位置指针向前移动
1
个字节。
该函数无出错返回值。
例如:
ch =
fgetc ( fp )
;
读/写一个字符串──fgets()和fputs()
int
fputs(
字符串,文件指针)
;
②功能:向指定文件输出一个字符串,并将读写位置指针向前移动
length
(
串长)
个字节。
如果输出成功,则函数返回值为
0
;否则,为非
0
值。
char
*
fgets
(
指针,串长+1,文件指针
);
②功能:从指定文件中读入一个字符串,存入
“
字符数组
/
指针
”
中,并在尾端自动加一个结束标志
'/0'
;同时,将读写位置指针向前移动
length
(
串长)
个字节。
注
:如果在读入规定长度之前,遇到文件尾EOF或换行符,读入即结束。
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
void main(int argc, char *argv[])
{ FILE *input, *output;
if( argc != 3)
{ printf("
参数个数不对
/n");
printf("/n Usage:
可执行文件名
source-file dest-file");
exit(0);
}
if (( input=fopen(argv[1],"r") )==NULL) /*
打开源文件失败
*/
{ printf("can not open source file/n");
exit(0);
}
if ((output=fopen(argv[2],"w"))==NULL) /*
创建目标文件失败
*/
{ printf("can not create destination file/n");
exit(0);
}
/*
复制源文件到目标文件中
*/
for( ; ( ! feof(input) ) ; ) fputc( fgetc(input), output );
fclose(input);
fclose(output); /*
关闭文件
*/
}
[
案例
]
密码管理程序。要求:
(
1
)密码设置(密码长度
6~12
个字符);
(
2
)加密存储到
1
个
ASCII
码文件中;
(
3
)登录密码校验。
算法设计要点:
(
1
)密码设置(密码长度
6~12
个字符)
(
2
)加密存储到
1
个
ASCII
码文件:字符串加密,请参阅
[
案例
6.4
]
。本案例直接利用
fputs()
函数,将加密后的密文写入密码文件
password.txt
。
(
3
)登录密码校验:首先提示用户输入密码,然后使用同一加密算法对用户输入的密码字符串进行加密,再与密码文件中存储的密文比较。
为突出本案例重点
——
对文件的读写操作,密码设置和密码串加密,留给读者自己设计和实现,本案例对密码字符串进行不加密存储和校验
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
#include "string.h"
void main( )
{ FILE *fp;
char password[13], password2[13];
if ( ( fp = fopen("password.txt", "w") )==NULL)
{ printf("/n can not open this file, press any key to exit......");
getch();
exit(0);
}
/*
设置、并存储密码
*/
printf("/n Setup a password(6-12 characters): "); gets(password);
fputs( password, fp );
fclose(fp);
/*
重新打开密码文件,读出密码字符串用于登录校验
*/
if ( ( fp = fopen("password.txt", "r") ) == NULL)
{ printf("/n can not open this file, press any key to exit......");
getch();
exit(0);
}
fgets( password, 13, fp );
fclose(fp);
printf("/n Input the password(6-12 characters): ");
gets( password2 );
if( strcmp(password2, password)==0 ) /*
密码正确
*/
printf("/n The password is correct, press any key to continue......");
else
printf("/n The password is incorrect, press any key to exit......");
getch( );
}
读/写一个数据块──fread()和fwrite()
1
.读
1
个数据块
——fread( )
int fread(void *buffer
,
int size
,
int count
,
FILE *fp)
;
从
fp
所指向文件的当前位置开始,一次读入
size
个字节,重复
count
次,并将读入的数据存放到从
buffer(
起始地址
)
开始的内存中;同时,将读写位置指针向前移动
size* count
个字节。
2
.写
1
个数据块
——fwrite ()
int fwrite( void *buffer
,
int size
,
int count
,
FILE *fp)
;
从
buffer
开始,一次输出
size
个字节,重复
count
次,并将输出的数据存放到
fp
所指向的文件中;同时,将读写位置指针向前移动
size* count
个字节。
如果调用
fread()
或
fwrite()
成功,则函数返回值等于
count
。
fread()
和
fwrite()
函数,一般用于二进制文件。
格式化读
/
写──
fscanf()
和
fprintf()
函数
与
scanf()
和
printf()
功能相似,区别在于:操作对象不同:
◆
scanf()
和
printf()
:标准输入
(stdin)
输出
(stdout)
文件。
◆
fscanf()
和
fprintf()
:指定文件。
int fscanf(
文件指针,
"
格式符
"
,输入变量首地址表
);
int fprintf(
文件指针,
"
格式符
"
,输出表达式表
);
读/写函数的选用原则
从功能角度来说,
fread()
和
fwrite()
函数可以完成对文件的任何操作。为方便起见,依下列原则选用:
1
.读
/
写
1
个字符
(
或字节
)
:选用
fgetc()
和
fputc()
。
2
.读
/
写
1
个
字符串:选用
fgets()
和
fputs()
。
3
.读
/
写
1
个
(
或多个
)
不含格式
的数据:选用
fread()
和
fwrite()
。
4
.读
/
写
1
个
(
或多个
)
含格式
的数据:选用
fscanf()
和
fprintf()
。
位置指针复位函数
rewind()
1
.用法:
int rewind(
文件指针
) ;
2
.功能:使文件的位置指针返回到文件头
随机读写与
fseek()
函数
对于流式文件,既可以顺序读写,也可随机读写,关键在于控制文件的位置指针。
◆顺序读写
:读写完当前数据后,系统自动将文件的位置指针,移动到下一个读写位置上。
◆随机读写
:读写完当前数据后,通过
fseek()
函数,将位置指针移动到文件中的任何一个地方。
1
.用法:
int fseek(
文件指针,位移量,参照点
);
2
.功能:将指定文件的位置指针,从参照点开始,移动指定的位移量。
(1)
参照点
:用
0
(
文件头
)
、
1
(
当前位置
)
和
2
(
文件尾
)
表示。
在
ANSI C
标准中,还规定如下符号常量:
SEEK_SET
──文件头,
SEEK_CUR
──当前位置,
SEEK_END
──文件尾
(2)
位移量
:以参照点为起点,向前
(
位移量
>
0
)
或后
(
位移量
<
0
)
移动的字节数。
在
ANSI C
标准中,要求位移量为
long int
数据。
假设文件的当前位置指针指向
50
(
从
0
开始编号
)
,则:
◆
fseek(fp, 10, 0)
:将位置指针移动到
10
;
◆
fseek(fp, 10, 1)
:将位置指针移动到
60
。
实际应用建议
:最好使用文件头作为参照点。
返回文件当前位置的函数
ftell()
文件的位置指针可任意移动,也经常移动,往往容易迷失当前位置,
ftell()
就可以解决这个问题。
1
.用法:
long ftell(
文件指针
) ;
2
.功能:返回文件位置指针的当前位置
(
用相对于文件头的位移量表示
)
。
如果返回值为
-1L
,则表明调用出错。
例如
: offset = ftell( fp )
;
if( offset = = -1L ) printf(“ftell() error/n”)
;
ferror()
函数
在调用
I/O
库函数时,如果出错,除函数返回值有所反映外,也可利用
ferror()
函数来检测。
1
.用法:
int ferror(
文件指针
)
;
2
.功能:返回
0—
未出错;返回非
0—
出错。
(1)
每次调用
I/O
函数,均产生一个新的
ferror()
值,所以应立即检测,否则出错信息会丢失。
(2)
在执行
fopen()
函数时,系统将
ferror()
的值自动置为
0
。
clearerr()
函数
1
.用法:
void clearerr(
文件指针
)
;
2
.功能:将
ferror()
和
feof()
函数值置为
0
。
对同一文件,只要出错就一直保留,直至遇到
clearerr()
函数或
rewind()
函数,或其它任何一个输入输出库函数。