您的位置:首页 > 其它

C的文件IO

2015-06-19 00:15 183 查看
IO的层次:

1. 底层IO:使用操作系统提供的的基础IO服务

2. 标准IO:使用C函数库和头文件"stdio.h"提供的标准包

C标准仅支持标准IO因为无法保证所有的操作系统使用相同的底层IO模型。标准IO除了便携性外,还有两个优点:

a). 它有很多能够简化处理不同IO问题的特殊函数

b). 输入和输出都是buffered的

stdout和stderr的一个区别是stderr是没有buffer的,错误的信息会直接输出

MS-DOS下用"Ctrl+Z"表示文件的结尾,但在Unix和Linux下它只是一个普通的字符;MS-DOS下用"\r\n"表示新的一行,当用text mode打开文件时,C程序会将"\r\n"视为"\n",但在binary mode下仍会看到"\r\n"

return和exit的区别:

1. 如果将main函数0设为递归函数,exit可以退出程序但return会将控制交给前一级递归直到最外层

2. 当在main函数之外的函数调用exit时也能够退出程序

fopen()函数

fopen()不仅打开了一个文件,还建立了一个buffer(如果是读写模式的话则有两个buffer)。第一个参数是要打开的文件名,更确切地说,是包含文件名字符串的地址。如果成功打开文件,fopen()会返回一个文件指针;如果打开失败,会返回一个NULL指针。文件指针的类型是pointer-to-FILE,它并不指向实际的文件,而只是指向包含关于文件信息的data
object,包括这个文件IO使用的buffer的信息。第二个参数是一个模式字符串,表明以什么方式打开文件。例:

FILE *fp;

fp = fopen(argv[1], "r");

fopen()第二个参数的选项:





对Unix和Linux等只有一种文件类型的系统来说,有"b"的模式和无"b"的模式相同

C11带有x的写模式有以下特点:

1. 如果在写模式下尝试打开一个已有的文件,x模式会打开失败而不是打开清空原文件内容,可以更好地保护原文件

2. x模式在当前处理关闭文件之前会阻止其他程序或线程访问该文件(取决于环境的允许情况)

fclose()函数

fclose(fp)关闭fp代表的文件并清空buffer。如果成功运行返回0,否则返回EOF

面向text的IO(处理字符和字符串)

getc()和putc()函数

二者类似getchar()和putchar(),区别在于需要指明使用的文件,如【ch = getc(fp); putc(ch, fp2);】;putc(ch, stdout)与putchar(ch)作用相同。当getc()读到文件结尾时会返回EOF,为了避免读取一个空的文件,应该在进入循环之前进行检查

fprintf()和fscanf()函数

fprintf()和fscanf()函数类似printf()和scanf(),区别在于他们要在第一个参数指明恰当的文件(注意putc是在最后一个参数指明文件)。如果fprintf输出的是数字,它其实只是将数字转换成字符进行输出,而并非输出数字本身的值

fprintf(stdout, "test: %s", argv[0]);

fprintf(fp, "%s\n", words);

fprintf(stderr, "fail");

fscanf(stdin, "%40s", words);

fgets()与fputs()函数(参考"C的字符串")

fgets()返回指向char型的指针,例:fgets(words, STLEN, fp); fputs(words, fp);

fseek(),ftell()和rewind()

fseek()

能够像处理数组一样处理文件,可以直接移动到一个被fopen()打开的文件的任意byte位置。fseek()的返回值是int型,返回0表明正常运行,返回-1表明出现问题(如移动范围超出文件边界)。它有三个参数:第一个是要处理文件的文件指针;第二个叫作offset,必须是long型但可正可负,表明从起始位置移动多远(单位是byte);第三个参数是模式,表明起始位置,可以是"SEEK_SET"(文件开头),"SEEK_CUR"(当前位置)或"SEEK_END"(文件结尾)

ftell()

返回在一个文件中的当前位置,返回值是long型。在ANSI C下,当以binary mode打开文件时,返回的是从开头到当前位置的byte数,如第一个byte是0;但text mode下打开则不一定是这样

ANSI C下,以text mode打开文件时,ftell()的返回值可以用作fseek()函数的第二个参数

rewind()

将文件指针重新指向文件开头,例:rewind(fp);

如果考虑程序的可移植性,需要注意:

1. 在binary mode下,具体的实现不一定支持SEEK_END模式,最具可移植性的方法是一个byte一个byte地读入文件直到结尾(但是这样比直接跳到文件结尾要慢)

2. 在text mode下,能保证有效的fseek()用法只有:



fgetpos()和fsetpos()

fseek()和ftell()的一个局限是他们只能处理大小能被long型表示的文件。ANSI C引入了两个能处理更大文件大小的位置函数,它们使用新类型fpos_t而非long型来表示文件位置。fpost_t类型不是一个基本类型,它是通过其他类型来定义的,但不能是数组类型。它可以有不同的实现来满足某个具体平台的需求,比如可以被定义成structure

fgetpos()的prototype:int fgetpos(FILE* restrict stream, fpos_t* restrict pos);

调用时,它在pos所指向的位置放置一个fpos_t值,这个值描述了文件中的一个位置。如果成功函数返回0,否则返回非0值

fsetpos()的prototype:int fsetpos(FILE* stream, const fpos_t* pos);

调用时,它用放在被pos指向的位置的fpost_t的值来将文件指针设定到由那个值所指向的位置。fpos_t的值必须是之前由调用fgetpos()获得的。若成功返回0,否则返回非0值

ungetc()

int ungetc(int c, FILE* fp):将一个字符退回输入流中,这个字符会被下一个读取文件流的函数取得

fflush()

int fflush(FILE *fp):将任何在output buffer中未写入的数据送到fp所指向的文件中,如果fp是空指针,则所有的output buffer都会被清空。在输入流上使用fflush()的结果是无法定义的

setvbuf()

int setvbuf(FILE* restrict fp, char* restrict buf, int mode, size_t size):为标准IO函数建立一个替代buffer。它在文件被打开但在这个流中尚未执行其他操作时被调用。指针fp指明针对的流;buf指向使用的存储,如果buf是NULL函数会自动分配一个buffer,如果不是NULL则必须自行创建buffer(比如创建一个1024长度的char型数组);size告知setvbuf()数组的大小;mode有以下选项:a)
_IOFBF表示当buffer满时flush;b) _IOLBF表示当buffer满时或出现newline时flush;c) _IONBF表示不使用buffer。如果函数成功返回0,否则返回非0

binary IO

面向text的IO只能存储字符而非数值,最准确且一致的存储数值的方式是用计算机使用的bit方式进行存储,这样的数据被称为以binary形式存储的。尽管所有的数据最终都是存储的binary数据,如果文件中的数据是以字符的形式呈现的,则说文件包含text data;如果所有的数据都是以binary形式的数值呈现的,则说文件包含binary data

对于Unix和Linux来说,用binary mode和text mode打开文件是一样的

fwrite()和fread()

fwrite()

size_t fwrite(const void* restrict ptr, size_t size, size_t nmemb, FILE* restrict fp);

fwrite()函数向文件中写入binary data。参数中,ptr是要写入数据块的地址;size代表数据块的总byte数;nmemb代表要写的数据块数;fp指向要写入的数据。函数的返回值是成功写入的项目数,通常等于nmemb,但如果发生错误的话可能会更小

例:double earnings[10]; fwrite(earnings, sizeof(double), 10, fp);

fread()

size_t fread(void* restrict ptr, size_t size, size_t nmemb, FILE* restrict fp);

fread()的参数与fwrite()相同,ptr是读入文件的数据的存储地址,fp指明要读取的文件。它的返回值是成功读取的项目数,通常等于nmemb,如果发生错误或遇到文件结尾的话会更小

例:double earnings[10]; fread(earnings, sizeof(double), 10, fp);

feof()和ferror()

当标准输入函数返回EOF时,通常是读到了文件的结尾,但也有可能是发生了错误,feof()和ferror()能区别这两种情况。

int feof(FILE* fp):如果最后一次调用到了文件结尾,则返回非0值,否则返回0

int ferror(FILE* fp):如果读写发生了错误返回非0值,否则返回0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: