文件类型
根据数据的组织形式,数据文件被称为文本文件或者二进制文件
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件
文本文件:拿记事本打开的文件都是文本文件
字符一律以ASCII形式存储,数据型数据既可以用ASCII形式存储,也可以使用二进制形式存储
文件缓冲区
ANSIC标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后一块送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将输入送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
输出:从程序到磁盘
输入:从磁盘到程序
文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件的状态及文件的位置等)。
这些信息是保存在一个结构体变量中,该结构体类型是FILE
不同C编译器,FILE类型包含的内容不完全相同
当打开文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充里面的信息,使用者不必关心细节
一般都是通过一个FILE的指针来维护这个FILE结构的变量
FILE* pf
文件的打开和关闭
int main ( )
{
FILE* pf = fopen ( "test.txt" , "w" ) ;
if ( pf == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
fclose ( pf) ;
pf = NULL ;
return 0 ;
}
文件的顺序读写
字符输入函数 - fgetc
int fgetc ( FILE * stream ) ;
Read a character from a stream ( fgetc, fgetwc) or stdin ( _fgetchar, _fgetwchar) .
fgetc ( ) 读取成功返回读到的字符,读取到文件末尾或读取失败时返回EOF
EOF - END IF FILE 文件结束标准 值为- 1
stream是文件流,流是程序输入或输出的一个连续的字节序列,设备的输入输出都是用流来处理的。
stdin 标准输入 键盘
stdout 标准输出 屏幕
int main ( )
{
int n = 0 ;
FILE* pf = fopen ( "test.txt" , "r" ) ;
if ( pf == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
while ( ( n= fgetc ( fp) ) != EOF )
{
printf ( "%d\n" , n) ;
}
return 0 ;
}
字符输出函数 - fputc
int fputc ( int c, FILE * stream ) ;
Writes a character to a stream ( fputc, fputwc) or to stdout ( _fputchar, _fputwchar) .
向指定的文件写入一个字符
写入成功返回写入的字符,失败时返回EOF
int main ( )
{
FILE* fp = fopen ( "test.txt" , "w" ) ;
if ( fp == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
char ch = 'a' ;
fputc ( ch, fp) ;
fclose ( fp) ;
fp = NULL ;
return 0 ;
}
文本行输入函数 - fgets
char * fgets ( char * string, int n, FILE * stream ) ;
Get a string from a stream.
从指定的文件中读取一个字符串,并保存到一个字符数组中
int main ( )
{
FILE* fp = fopen ( "test.txt" , "r" ) ;
if ( fp == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
char str[ 100 ] = { 0 } ;
fgets ( str, 5 , fp) ;
printf ( "%s\n" , str) ;
fclose ( fp) ;
fp = NULL ;
return 0 ;
}
本文行输出函数 - fputs
int fputs ( const char * string, FILE * stream ) ;
Write a string to a stream.
向指定的文件写一个字符串
写入成功返回非负数,失败返回EOF
int main ( )
{
FILE* fp = fopen ( "test.txt" , "w" ) ;
if ( fp == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
fputs ( "hello world\n" , fp) ;
fputs ( "haha\n" , fp) ;
fclose ( fp) ;
fp = NULL ;
return 0 ;
}
文件拷贝
int main ( )
{
FILE* fp = fopen ( "test1.txt" , "r" ) ;
if ( fp == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
FILE* fpp = fopen ( "test2.txt" , "w" ) ;
if ( fpp == NULL )
{
perror ( "fopen tw" ) ;
return 1 ;
}
int ch = 0 ;
while ( ( ch = fgetc ( fp) ) != EOF )
{
fputc ( ch, fpp) ;
}
fclose ( fp) ;
fp = NULL ;
fclose ( fpp) ;
fpp = NULL ;
return 0 ;
}
格式化输入函数 - fscanf
int fscanf ( FILE * stream, const char * format [ , argument ] . . . ) ;
Read formatted data from a stream.
从磁盘中读取内容
从一个流中格式化输入,遇到空格和换行时结束
成功返回输入参数的个数,失败返回EOF
struct Stu
{
char name[ 20 ] ;
int age;
char sex[ 5 ] ;
} ;
int main ( )
{
struct Stu s = { 0 } ;
FILE* fp = fopen ( "test.txt" , "r" ) ;
if ( fp == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
fscanf ( fp, "%s %d %s" , s. name, & ( s. age) , s. sex) ;
printf ( "%s %d %s\n" , s. name, s. age, s. sex) ;
fclose ( fp) ;
fp = NULL ;
return 0 ;
}
格式化输出函数 - fprintf
int fprintf ( FILE * stream, const char * format [ , argument ] . . . ) ;
Print formatted data to a stream.
struct Stu
{
char name[ 20 ] ;
int age;
char sex[ 5 ] ;
} ;
int main ( )
{
struct Stu s = { "zhangsan" , 18 , "man" } ;
FILE* fp = fopen ( "test.txt" , "w" ) ;
if ( fp == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
fprintf ( fp, "%s %d %s" , s. name, s. age, s. sex) ;
fclose ( fp) ;
fp = NULL ;
return 0 ;
}
sprintf
int sprintf ( char * buffer, const char * format [ , argument] . . . ) ;
Write formatted data to a string.
struct Stu
{
char name[ 20 ] ;
int age;
char sex[ 5 ] ;
} ;
int main ( )
{
struct Stu s = { "zhangsan" , 18 , "man" } ;
char str[ 100 ] = { 0 } ;
sprintf ( str, "%s%d%s" , s. name, s. age, s. sex) ;
printf ( "%s\n" , str) ;
return 0 ;
}
sscanf
int sscanf ( const char * buffer, const char * format [ , argument ] . . . ) ;
Read formatted data from a string.
# include <stdio.h>
struct Stu
{
char name[ 20 ] ;
int age;
char sex[ 5 ] ;
} ;
int main ( )
{
struct Stu s = { "zhangsan" , 18 , "man" } ;
struct Stu tmp = { 0 } ;
char str[ 100 ] = { 0 } ;
sprintf ( str, "%s %d %s" , s. name, s. age, s. sex) ;
sscanf ( str, "%s %d %s" , tmp. name, & ( tmp. age) , tmp. sex) ;
printf ( "%s %d %s\n" , tmp. name, tmp. age, tmp. sex) ;
return 0 ;
}
二进制输出函数 - fwrite
size_t fwrite ( const void * buffer, size_t size, size_t count, FILE * stream ) ;
Writes data to a stream.
size:每个元素的大小,以字节为单位
count:元素个数,每个元素的大小是size字节
int main ( )
{
FILE* fp = fopen ( "test.txt" , "wb" ) ;
if ( fp == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
char name[ ] = "zhangsan" ;
fwrite ( name, sizeof ( name) , 1 , fp) ;
fclose ( fp) ;
fp = NULL ;
return 0 ;
}
二进制输入函数 - fread
size_t fread ( void * buffer, size_t size, size_t count, FILE * stream ) ;
Reads data from a stream.
从给定的输入流读取最多count个对象到数组中
int main ( )
{
FILE* fp = fopen ( "test.txt" , "rb" ) ;
if ( fp == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
char name[ 100 ] = { 0 } ;
fread ( name, 8 , 1 , fp) ;
printf ( "%s\n" , name) ;
fclose ( fp) ;
fp = NULL ;
return 0 ;
}
文件的随机读写
fseek
int fseek ( FILE * stream, long offset, int origin ) ;
Moves the file pointer to a specified location.
offset:偏移量
origin:位置
调整文件指针位置的函数
int main ( )
{
FILE* fp = fopen ( "test.txt" , "w" ) ;
if ( fp == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
fputs ( "ABCDEF" , fp) ;
fseek ( fp, - 3 , SEEK_END ) ;
fputc ( 'Q' , fp) ;
fclose ( fp) ;
fp = NULL ;
return 0 ;
}
ftell
long ftell ( FILE * stream ) ;
Gets the current position of a file pointer.
计算某一个位置相对于起始位置的偏移量
int main ( )
{
FILE* fp = fopen ( "test.txt" , "w" ) ;
if ( fp == NULL )
{
perror ( "fopen" ) ;
return 1 ;
}
fputs ( "ABCDEF" , fp) ;
fseek ( fp, 4 , SEEK_SET ) ;
int ret = ftell ( fp) ;
printf ( "%d\n" , ret) ;
fclose ( fp) ;
fp = NULL ;
return 0 ;
}
rewind
void rewind ( FILE * stream ) ;
Repositions the file pointer to the beginning of a file.
让文件指针的位置回到文件的起始位置
文件结束的判定
在文件读取时,不能用feof函数的返回值直接用来判断文件是否结束
而是用于当文件读取结束的时候,判断是读取失败,还是遇到文件尾结束
1. 文本文件读取是否结束,判断返回值是否为EOF (fgetc),或者NULL (fgets)
2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数