文件内容和二进制内容:
文本格式和二进制格式:
文本模式和二进制模式:
所有文件都是以二进制形式存储,但是如果文件最初使用二进制编码的字符表示文本,该文本就是文本文件,其中包含文本内容
如果文件中的二进制值代表机器语言代码或数值数据或图片或音乐编码,该文件就算二进制文件,其中包含二进制内容。
UNIX用同一种文件格式处理文本文件和二进制文件内容。
为了规范文本文件的处理,C中提供了两种访问文件的途径:二进制模式和文本模式,在二进制模式中,程序可以访问文件的每个字节。而在文本模式中,程序所见的内容和实际内容不同
程序以文本模式读取文件是,把本地环境表示的行尾或文件结尾映射为C模式
I/O的级别:处理访问文件的两个级别底层I/O(使用操作系统提供的基本I/O服务),标准高级I/O(使用C库中的标准包和stdio.h头文件定义)
因无法保证所有的操作系统都使用相同的底层I/O,股,C标准只支持标准I/O包
标准文件:
C程序会打开三个文件,它们被称为标准输入、标准输出和标准错误输出,
通常标准输入为程序提供输入,它是getchar 和scanf使用的文件,程序通常输出到标准输出,它是putchar\puts\printf使用的文件
标准IO:
标准IO的输入输出都是缓冲的,也就是说,一次转移一大块信息而不是一字节信息,如:当程序读取文件时,一块数据被拷贝至缓冲区(一块中介存储区域),这种缓冲区极大地提高了数据传输效率
程序可以检查缓冲区中的字节,缓冲在后台处理,所以给人逐字符访问的错觉。
fopen函数:
r 以读模式damia文件
w 以写模式打开文件,把现有文件的长度截为0,如果文件不存在,则创建一个新文件
a 以写模式打开一个文件,但在现有文件末尾添加内容,如果文件不存在则创建一个
r+ 以更新模式打开文件(即可读写模式)
w+ 以更新模式打开文件如果文件存在则将其长度截为0,如果文件不存在则新建一个
a+ 以更新模式打开文件在现有文件的末尾添加内容哦你,如果文件不存在则新建一个,可以读整个文件,但是只能从末尾添加内容
rb\wb\ab\ab+\a+b\wb+\w+b\ab+\a+b 与上一个模式类似,但是是以二进制模式而不是文本模式打开文件
wx\wbx\w+x\wb+x\w+bx 类似非x模式,但是如果文件已存在或以独占模式打开文件,则打开文件失败。
程序成功打开文件之后,函数返回文件 指针,其他的IO函数可以使用这个指针指定该文件,其他函数可以使用这个指针指定该文件,
文件指针的类型是指向FILE的指针,FILE是定义在stdio.h中的一个派生类型,文件指针fp并不指向实际的文件,它指向一个包含文件信息的数据对象,其中包含的操作文件的IO函数所用的缓冲区信息
因为标准库中的IO函数使用缓冲区,所以它不仅要知道缓冲区的位置,还要知道缓冲区被填充的程度以及操作哪一个文件。标准IO函数根据这些信息在必要时决定再次填充或清空缓冲区
gets()和puts()函数
标准输入流
标准输出流
标准错误输出流
fopen()函数:
int main(int argc,char * argv[])
FILE *FP /声明一个指向文件的指针
fp = fopen(argv[1],"r") /fopen函数的第一个参数的值为指向文件名的指针
第二个参数的值为声明这个函数到底是以什么方式来读取这个文件
共有 “r” 读模式; "w" 写模式 如果文件存在,则清空内容;“a” 写模式,在现有文件的末尾添加内容
“r+”更新模式;“w+”以更新模式读写,如果文件存在则清空内容;“a+”以更新模式在打开的文件末尾加内容
以上这些如果加b一起用,如:“rb”,"a+b","ab+"等,都是在原有的模式上以二进制打开文件
如果加x一起用的话,如:"wx,xb+x,w+x"等,则在打开已有文件或者以独占模式打开文件时,打开失败
fopen 函数返回一个文件指针,fp并不指向实际的文件对象,它指向一个包含文件信息的数据结构,其中包含操作文件的IO函数所用的缓冲区信息,因为标准库中的IO函数使用缓冲区,所以它们不仅仅要知道缓冲区的位置,还要知道缓冲区被填充的程度以及操作的哪一个文件,标准IO函数再根据这些信息决定再次填充或者清空缓冲区,fp指向的数据对象包含了这些信息(该数据对象是一个C结构)
fopen函数不仅仅是打开一个文件,而且还创建里一个缓冲区,以及一个包含了文件和缓冲区数据的结构
getc()和putc()函数
这两个函数和getchar()还有putchar()类似
所不同的是getchar()是不需要参数可以直接从控制台输入或者从其他来源直接获取一个字符输入,他不需要知道来源,只需要接收字符就行了,而对于getc()来说,必须要告诉它你从那个文件来源获取输入,例如:
c = getchar();
c = getc(fp); //fp为文件指针
putchar()和putc()函数的关系也与上述两个函数类似,
putc(ch,stdout)函数这样写的作用和putchar(ch)是一样的,都是在向控制台输出一个字符,stdout是系统定义的标准输出相关联的指针,可以将stdout这个参数改为fp,意为将字符输出到fp指针指向的数据结构从而写入文件中
如:putc(ch,fp) //就是将ch写入到fp指向的结构体中从而写入文件中
EOF:用来表示文件的末尾,一般用作读文件的读取的判断。
如:int ch; FILE * fp;
ch = getc(fp); //开始获取输入
if(ch != EOF){ ......} //进行判断文件是否读到了末尾
fclose()函数,用来关闭指定的读取流的,必要时会刷新缓冲区,成功关闭流则会返回0,失败返回EOF,磁盘已满或移动硬盘被移除或出现IO错误都会导致关闭失败。
stdio.h中定义了3个文件指针和标准文件相关联
标准输入 stdin 键盘
标准输出 stdout 显示器
标准输出 stderr 显示器
这些都是指向FILE的指针,所以它们以用作标准IO函数的参数
文件IO:fprintf()和fscanf()、fgets()和fputs()
文件IO函数需要使用FILE指针先指定待处理的文件,与gets()和puts()类似,这些函数都要求指向FILE的指针指定一个文件,或者,使用fopen()返回值
rewind(fp)//通过文件指针让程序返回文件开始处读取
fprintf(stdout,".....");第一个参数为文件指针
fscanf(stdin,"...");第一个参数为文件指针
fgets(buf,STLEN,fp); //第一个参数和gets()一样,夜色表示储存输入位置的地址,第二个参数是一个整数,表示待输入的字符串的大小,最后一个参数表示文件指针,指定待读取的文件
fputs(buf,fp);//buf为字符串地址,fp为指定文件的文件指针
随机访问函数fseek()和ftell()函数
有了fseek()函数,便可把文件看作是数组,中fopen()打开的文件中直接移动到任意字节处,fseek()函数有三个参数,返回int类型的值,ftell()函数返回一个long类型的值,表示当前位置
fseek(fp,count,SEEK_END) //fp文件指针指向的文件应该是已经使用fopen()打开的文件流,count在函数中表示字符地址的偏移量,该值必须为long值,而且以正值(+)标志正偏移量
负值(-)表示负偏移量,0表示不动。SEEK_SET表示文件开始处,SEEK_CUR表示当前位置,SEEK_END表示文件末尾。
可使用如下方式表示:fseek(fp,0L,SEEK_SET)//表示定位到文件开始处
fseek(fp,10L,SEEK_SET)//定位至文件中的第10个字节
fseek(fp,2L,SEEK_CUR)//从文件当前位置开始前移2个字节
fseek(fp,0L,SEEK_END)//定位至文件末尾
fseek(fp,-10L,SEEK_END)//从文件结尾处回退10个字节
如果一切执行正常,则返回值为0rugosa出现错误(如地址越界),则返回-1
ftell()函数的返回值类型为Long,其返回的是当前位置。
上诉fseek()和ftell()函数的限制在于将文件的大小都限制在了Long 类型的范围
而对于fgetpos()和fsetpos()函数中则无此限制,这两个函数专门对大文件进行读取,者两个函数使用了自定义的类型fpos_t,这个类型是根据其他类型来定义的,不能为数组类型;
标准IO工作原理
使用fopen函数将文件打开,并创建一块缓冲区(内存大小一般为512k,或其整数倍),然后再调用标准输入流函数(如:fgets(),fscanf(),getc()等),从文件中将数据快读取到缓冲区中
,并设置fp指向的结构中的值,并设置流中的当前位置和拷贝进缓冲区的数据大小,通常当前位置从0字节开始,然后,按要求,输入函数从缓冲区中向内存中读取数据,每读取一个字符,其文件指示器
的值就指向下一个字符的位置,并且标准输入函数(stdin.h)中的所有函数使用的都是相同的缓冲区,所以,它们对文件的读取通常都是连续的,下一个函数从上一个函数的结束位置开始读取,每当一块数据块读取完的时候,
再从文件中将下一个文件块读取到缓冲区中,重复以上的步骤,直到文件读取完毕,输出函数也是按照一样的流程进行输出。
二进制IOfread()和fwrite()函数
size_t fwrite()函数
size_t是根据标准C定义的类型,他是sizeof运算符的返回类型,通常为unsigned int; sizeof返回size_t类型的值,如使用 size_t instsize;intsize = sizeof(int);
C中也可以使用typedef为类型创建别名,如typedef double real;这样使用real就可以创建double的数据。
size_t fwrite(const void * restrict ptr;size_t size; size_t nmemb,FILE * restrict fp);指针ptr表示代写入数据块的地址,size表示了代写入数据块的大小,nmemb表示代写入数据块的个数,而fp则指定代写入的文件,
将ptr指向的数据块写入到fp指向的文件中。ptr的类型不是固定的类型,其可以为任意类型,但在调用过程中,会自动转换为void类型,
正常情况下,fwrite函数的返回值就是写入数据块的个数,也就是nmemb的值,如果出现错误,则返回值比nmemb小。
fwrite函数是从内存写出到文件,而相反的fread则是从文件读入到内存中,fread函数的参数和fwrite是一样的,只是,ptr和fp表示的意思相反,
fread(const void * ptr,size_t size,size_t nmemb,FILE* restrict fp),返回值也与fwrite一样,如果出现错读或者是读取到了文件末尾则返回值小于nmemb;
int fflush(FILE * fp)函数 刷新缓冲区 如果fp是空指针,则所有缓冲区都被刷新,只要最近一次操作不是输入操作,就可以使用该函数来更新流。
int setvbuf()函数,这个函数是用来声明一块缓冲区的,
int setvbuf(FILE * restrict fp,char * restrict buf,int mode,size_t size)
使用这个函数创建一个供标准IO函数thatn使用的缓冲区,在打开文件后且没有进行其他的流操作之前调用这个函数,,指针fp识别待处理的流,buf指向待使用的存储区,如果buf的值不是NULL,则必须穿件一个缓冲区,例如,声明一个内含1024个字符的素组,并传递该数组的地址,然而,如果把NULL作为buf的值,该函数会为真机分配一个缓冲区,变量size告诉setvbuf()数组的大小
mode有3种选择,_IOFBF表示完全缓冲(即在缓冲区满的时候进行缓冲),_IOLBF表示行缓冲(即在缓冲区满时或写入一个换行符),_IONBF表示无缓冲,如果操作成功,函数返回0,否则返回一个非0值。
标准输入流
标准输出流
标准错误输出流
fopen()函数:
int main(int argc,char * argv[])
FILE *FP /声明一个指向文件的指针
fp = fopen(argv[1],"r") /fopen函数的第一个参数的值为指向文件名的指针
第二个参数的值为声明这个函数到底是以什么方式来读取这个文件
共有 “r” 读模式; "w" 写模式 如果文件存在,则清空内容;“a” 写模式,在现有文件的末尾添加内容
“r+”更新模式;“w+”以更新模式读写,如果文件存在则清空内容;“a+”以更新模式在打开的文件末尾加内容
以上这些如果加b一起用,如:“rb”,"a+b","ab+"等,都是在原有的模式上以二进制打开文件
如果加x一起用的话,如:"wx,xb+x,w+x"等,则在打开已有文件或者以独占模式打开文件时,打开失败
fopen 函数返回一个文件指针,fp并不指向实际的文件对象,它指向一个包含文件信息的数据结构,其中包含操作文件的IO函数所用的缓冲区信息,因为标准库中的IO函数使用缓冲区,所以它们不仅仅要知道缓冲区的位置,还要知道缓冲区被填充的程度以及操作的哪一个文件,标准IO函数再根据这些信息决定再次填充或者清空缓冲区,fp指向的数据对象包含了这些信息(该数据对象是一个C结构)
fopen函数不仅仅是打开一个文件,而且还创建里一个缓冲区,以及一个包含了文件和缓冲区数据的结构
getc()和putc()函数
这两个函数和getchar()还有putchar()类似
所不同的是getchar()是不需要参数可以直接从控制台输入或者从其他来源直接获取一个字符输入,他不需要知道来源,只需要接收字符就行了,而对于getc()来说,必须要告诉它你从那个文件来源获取输入,例如:
c = getchar();
c = getc(fp); //fp为文件指针
putchar()和putc()函数的关系也与上述两个函数类似,
putc(ch,stdout)函数这样写的作用和putchar(ch)是一样的,都是在向控制台输出一个字符,stdout是系统定义的标准输出相关联的指针,可以将stdout这个参数改为fp,意为将字符输出到fp指针指向的数据结构从而写入文件中
如:putc(ch,fp) //就是将ch写入到fp指向的结构体中从而写入文件中
EOF:用来表示文件的末尾,一般用作读文件的读取的判断。
如:int ch; FILE * fp;
ch = getc(fp); //开始获取输入
if(ch != EOF){ ......} //进行判断文件是否读到了末尾
fclose()函数,用来关闭指定的读取流的,必要时会刷新缓冲区,成功关闭流则会返回0,失败返回EOF,磁盘已满或移动硬盘被移除或出现IO错误都会导致关闭失败。
stdio.h中定义了3个文件指针和标准文件相关联
标准输入 stdin 键盘
标准输出 stdout 显示器
标准输出 stderr 显示器
这些都是指向FILE的指针,所以它们以用作标准IO函数的参数
文件IO:fprintf()和fscanf()、fgets()和fputs()
文件IO函数需要使用FILE指针先指定待处理的文件,与gets()和puts()类似,这些函数都要求指向FILE的指针指定一个文件,或者,使用fopen()返回值
rewind(fp)//通过文件指针让程序返回文件开始处读取
fprintf(stdout,".....");第一个参数为文件指针
fscanf(stdin,"...");第一个参数为文件指针
fgets(buf,STLEN,fp); //第一个参数和gets()一样,夜色表示储存输入位置的地址,第二个参数是一个整数,表示待输入的字符串的大小,最后一个参数表示文件指针,指定待读取的文件
fputs(buf,fp);//buf为字符串地址,fp为指定文件的文件指针
随机访问函数fseek()和ftell()函数
有了fseek()函数,便可把文件看作是数组,中fopen()打开的文件中直接移动到任意字节处,fseek()函数有三个参数,返回int类型的值,ftell()函数返回一个long类型的值,表示当前位置
fseek(fp,count,SEEK_END) //fp文件指针指向的文件应该是已经使用fopen()打开的文件流,count在函数中表示字符地址的偏移量,该值必须为long值,而且以正值(+)标志正偏移量
负值(-)表示负偏移量,0表示不动。SEEK_SET表示文件开始处,SEEK_CUR表示当前位置,SEEK_END表示文件末尾。
可使用如下方式表示:fseek(fp,0L,SEEK_SET)//表示定位到文件开始处
fseek(fp,10L,SEEK_SET)//定位至文件中的第10个字节
fseek(fp,2L,SEEK_CUR)//从文件当前位置开始前移2个字节
fseek(fp,0L,SEEK_END)//定位至文件末尾
fseek(fp,-10L,SEEK_END)//从文件结尾处回退10个字节
如果一切执行正常,则返回值为0rugosa出现错误(如地址越界),则返回-1
ftell()函数的返回值类型为Long,其返回的是当前位置。
上诉fseek()和ftell()函数的限制在于将文件的大小都限制在了Long 类型的范围
而对于fgetpos()和fsetpos()函数中则无此限制,这两个函数专门对大文件进行读取,者两个函数使用了自定义的类型fpos_t,这个类型是根据其他类型来定义的,不能为数组类型;
标准IO工作原理
使用fopen函数将文件打开,并创建一块缓冲区(内存大小一般为512k,或其整数倍),然后再调用标准输入流函数(如:fgets(),fscanf(),getc()等),从文件中将数据快读取到缓冲区中
,并设置fp指向的结构中的值,并设置流中的当前位置和拷贝进缓冲区的数据大小,通常当前位置从0字节开始,然后,按要求,输入函数从缓冲区中向内存中读取数据,每读取一个字符,其文件指示器
的值就指向下一个字符的位置,并且标准输入函数(stdin.h)中的所有函数使用的都是相同的缓冲区,所以,它们对文件的读取通常都是连续的,下一个函数从上一个函数的结束位置开始读取,每当一块数据块读取完的时候,
再从文件中将下一个文件块读取到缓冲区中,重复以上的步骤,直到文件读取完毕,输出函数也是按照一样的流程进行输出。
二进制IOfread()和fwrite()函数
size_t fwrite()函数
size_t是根据标准C定义的类型,他是sizeof运算符的返回类型,通常为unsigned int; sizeof返回size_t类型的值,如使用 size_t instsize;intsize = sizeof(int);
C中也可以使用typedef为类型创建别名,如typedef double real;这样使用real就可以创建double的数据。
size_t fwrite(const void * restrict ptr;size_t size; size_t nmemb,FILE * restrict fp);指针ptr表示代写入数据块的地址,size表示了代写入数据块的大小,nmemb表示代写入数据块的个数,而fp则指定代写入的文件,
将ptr指向的数据块写入到fp指向的文件中。ptr的类型不是固定的类型,其可以为任意类型,但在调用过程中,会自动转换为void类型,
正常情况下,fwrite函数的返回值就是写入数据块的个数,也就是nmemb的值,如果出现错误,则返回值比nmemb小。
fwrite函数是从内存写出到文件,而相反的fread则是从文件读入到内存中,fread函数的参数和fwrite是一样的,只是,ptr和fp表示的意思相反,
fread(const void * ptr,size_t size,size_t nmemb,FILE* restrict fp),返回值也与fwrite一样,如果出现错读或者是读取到了文件末尾则返回值小于nmemb;
int fflush(FILE * fp)函数 刷新缓冲区 如果fp是空指针,则所有缓冲区都被刷新,只要最近一次操作不是输入操作,就可以使用该函数来更新流。
int setvbuf()函数,这个函数是用来声明一块缓冲区的,
int setvbuf(FILE * restrict fp,char * restrict buf,int mode,size_t size)
使用这个函数创建一个供标准IO函数thatn使用的缓冲区,在打开文件后且没有进行其他的流操作之前调用这个函数,,指针fp识别待处理的流,buf指向待使用的存储区,如果buf的值不是NULL,则必须穿件一个缓冲区,例如,声明一个内含1024个字符的素组,并传递该数组的地址,然而,如果把NULL作为buf的值,该函数会为真机分配一个缓冲区,变量size告诉setvbuf()数组的大小
mode有3种选择,_IOFBF表示完全缓冲(即在缓冲区满的时候进行缓冲),_IOLBF表示行缓冲(即在缓冲区满时或写入一个换行符),_IONBF表示无缓冲,如果操作成功,函数返回0,否则返回一个非0值。