5.1 引言
5.2 流和FILE对象
对于标准I/O库,它们的操作则是围绕流(stream)进行的。当用标准I/O库打开或创建一个文件时,我们已使一个流与一个文件相结合.
当打开一个流时,标准I/O函数fopen返回一个指向FILE对象的指针。该对象通常是一个结构,它包含了IO库为管理该流所需要的所有信息:
用于实际I/O的文件描述符,指向流缓存的指针,缓存的长度,当前在缓存中的字符数,出错标志等等。
#include <stdio.h>
#include <wchar.h>
int fwide (FILE* fp, int mode);
如果流的方向被确定了,那么fwide函数不会改变流的方向。否则,fwide会设置流的方向
如果mode小于0,流将被设置为字节方向;如果mode大于0,流将被设置为宽方向。
如果mode为0,则不改变方向 无论是否改变,返回值都会存在,用于确定流的方向
5.3 标准输入、标准输出和标准出错
这三个标准I / O流通过预定义文件指针 stdin , stdout和stderr加以引用.
5.4 缓冲
标准I/O提供了三种类型的缓存:
全缓存。在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。
行缓存。在这种情况下,当在输入和输出中遇到新行符时,标准 I/O库执行I/O操作。
不带缓存。标准 I / O库不对字符进行缓存。
SVR4和4.3+BSD的系统默认使用下列类型的缓存:
• 标准出错是不带缓存的。
• 如若是涉及终端设备的其他流,则它们是行缓存的;否则是全缓存的。
对任何一个给定的流,如果我们并不喜欢这些系统默认,则可调用下列两个函数中的一个更改缓存类型:
#include <stdio.h>
void setbuf (FILE* fp, void* buf);
void setvbuf (FILE* fp, void* buf, int mode, size_t size);
如果在一个函数中分配一个自动变量类的标准 I / O缓存,则从该函数返回之前,必须关闭该流。
一般而言,应由系统选择缓存的长度,并自动分配缓存。在这样处理时,标准I/O库在关闭此流时将自动释放此缓存。
任何时候,我们都可强制刷新一个流:
#include<stdio.h>
int fflush (FILE* fp);
此函数使该流所有未写的数据都被传递至内核。作为一种特殊情形,如若fp是NULL,则此函数刷新所有输出流.
5.5 打开流
#include <stdio.h>
FILE* fopen (const char* pathname, const char* mode);
FILE* freopen (const char* pathname, const char* mode, FILE* fp);
//此函数一般用于将一个指定的文件打开为一个预定义的流:标准输入、标准输出或标准出错。
FILE* fdopen (int fd, const char* mode);
//此函数常用于由创建管道和网络通信通道函数获得的插述符。
type参数指定对该I/O流的读、写方式, ANSI C规定type参数可以有15种不同的值:
注意:
对于以a+ 或a方式打开文件时,每次读写之前,先将文件表项中的当前文件偏移量设为inode中的文件长度。
对于fdopen, type参数的意义则稍有区别。
因为该描述符已被打开,所以type的取值受限于已设定的文件状态标志。
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char* argv[]){
int fd = open (argv[1], O_RDONLY); // 设定只读文件状态标志
char buf[BUFSIZ] = "HELLOWORLD";
write(fd, buf, 10);
FILE* fp = fdopen(fd,"w"); // fd 等于 NULL
if (fp)
fprintf(stdout, "succeed to fdopen %s \n", argv[1]);
else
fprintf(stdout, "fail to fdopen %s \n", argv[1]);
fclose(fp);
return 0;
}
print "fail to fdopen"
不管文件状态标志O_TRUNC有没有设置,fdopen为写而打开并不截短该文件(“w+”无效,但不返回错误)
int main(int argc, char* argv[]){
int fd = open (argv[1], O_RDWR | O_TRUNC);
char buf[BUFSIZ] = "HELLO WORLD";
write(fd, buf, 11);
FILE* fp = fdopen(fd,"w+");
putc('c',fp);
if (fp)
fprintf(stdout, "succeed to fdopen %s \n", argv[1]);
else
fprintf(stdout, "fail to fdopen %s \n", argv[1]);
fclose(fp);
return 0;
}
// 文件内容为"HELLO WORLDc",而不是 “c”
当以读和写类型打开一文件时( type中+号),具有下列限制:
• 如果中间没有fflush、 fseek、 fsetpos或rewind,则在输出的后面不能直接跟随输入。
• 如果中间没有fseek、 fsetpos或rewind ,或者一个输出操作没有到达文件尾端,则在输入操作之后不能直接跟随输出。
int main(int argc, char* argv[]){
FILE* fp = fopen(argv[1],"r+");
char ch = fgetc(fp);
fputc(ch, fp);
return 0;
}
// 按照课本意思,这段代码应该是无法成功执行的,但在linux 3.10.0、 gcc 4.8.3 平台上可以成功执行 ?? 疑问
在指定w或a类型创建一个新文件时,我们无法说明该文件的存取许可权位(第3章中所述的open函数和creat函数则能做到这一点)。
POSIX.1要求以这种方式创建的文件具有下列存取许可权:
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH. 但可以通过umask值来限制这些权限.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。