标准io
标准I/O介绍
概念:
一组相关数据的有序集合
文件类型:
常规文件 r
目录文件 d
字符设备文件 c
块设备文件 b
管道文件 p
套接字文件 s
符号链接文件 l
UNIX基础知识-系统调用和库函数
标准I/O由ANSI C标准定义
主流操作系统上都实现了C库
标准I/O通过缓冲机制减少系统调用,实现更高的效率
FILE
标准IO用一个结构体类型来存放打开的文件的相关信息
标准I/O的所有操作都是围绕FILE来进行
FILE结构体的中的类型和含义如下:
struct _IO_FILE {
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags
/* The following pointers correspond to the C++ streambuf protocol. */
/* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr; /* Current read pointer */
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
#if 0
int _blksize;
#else
int _flags2;
#endif
_IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary */
/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
/* char* _save_gptr; char* _save_egptr; */
_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
流(stream)
FILE又被称为流(stream)
文本流/二进制流
文本流和二进制流在不同的系统中最大的区别是换行符
Windows
windows是区分文本流和二进制流的
二进制流: 换行符 ‘\n’ 对应的是一个字符
文本流: 换行符 ‘\r’ ‘\n’ 对应的是两个字符
linux中并不区分二进制流和文本流,或者说linux中就是二进制流
Linux: 换行符 ‘\n’
标准I/O – 流的缓冲类型
1.全缓冲,当流的缓冲区中满的时候才执行文件的操作,这是写的时候;
读的时候,第一次读的时候,首先会把第一批数据都读到缓冲区里,然后每次从缓冲区中读取内容,当缓冲区空的时候,才会再从实际的文件中读一批数据进来,当打开一个普通文件的时候,默认的是全缓冲;
2.行缓冲,当输入和输出遇到换行符“\n“时,进行i/o操作,当流和一个终端关联时,就是典型的行缓冲,其实就是标准输入和标准输出流,因为标准输入和标准输出都是和终端相关联的,所以他们的默认类型都是行缓存;
3.无缓冲,数据直接写入文件,流不进行缓冲,标准错误流就是典型的无缓冲;
标准i/o—stdin/stdout/stderr
标准i/o预定义了三个流,程序运行时会自动打开,分别是:
标准输入流 文件描述符:0 STDIN_FILENO stdin
标准输出流 文件描述符:1 STDOUT_FILENO stdout
标准错误流 文件描述符:2 STDERR_FILENO stderr
标准i/o就是标准C中定义好的一组用来输入输出的API函数
标准I/O – 打开流
下列函数可用于打开一个标准I/O流:
FILE *fopen (const char *path, const char *mode);
成功时返回流指针;出错时返回NULL
mode参数:
“r” 或 “rb” 以只读方式打开文件,文件必须存在。
“r+” 或 ”r+b” 以只读方式打开文件,文件必须存在。
“w” 或 “wb” 以只写方式打开文件,若文件存在则文件长度清为0。若文件不存在则创建。
“w+” 或 “w+b” 以读写方式打开文件,其他同”w”。
“a” 或 “ab” 以只写方式打开文件,若文件不存在则创建;向文件写入的数
据被追加到文件末尾。
“a+” 或 “a+b” 以读写方式打开文件。其他同”a”
这里的b参数表示二进制方式打开文件,linux下忽略改参数;
创建新文件的权限:
1.fopen() root用户下,创建的文件访问权限是0666(rw-rw-rw),0666中的”0“表示八进制;
2.linux系统中umask设定会影响文件的访问权限,其规则为(0666&~umask)例如:
fopen的默认权限是0666,root下的掩码是022,分别换算为二进制后是:110 110 110和~1010(波浪号是按位取反的意思)=111 101 101;经过&运算后得:110 100 100,换算八进制后是0644;
用户可以通过umask函数或者命令修改相关设定
标准I/O – 处理错误信息
extern int errno;
void perror(const char *s);
char *strerror(int errno);
errno 存放错误号,由系统生成
perror先输出字符串s,再输出错误号对应的错误信息
strerror根据错误号返回对应的错误信息
标准I/O – 错误信息处理 – 示例1
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
if ((fp = fopen(“test.txt”, “r+”)) == NULL) {
perror(“fopen”);
return -1;
}
标准I/O – 错误信息处理 – 示例2
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
FILE *fp;
if ((fp = fopen(“test.txt”, “r+”)) == NULL) {
printf(“fopen: %s\n”, strerror(errno));
return -1;
}
标准I/O – 关闭流
int fclose(FILE *stream);
fclose()调用成功返回0,失败返回EOF,并设置errno
流关闭时自动刷新缓冲中的数据并释放缓冲区
当一个程序正常终止时,所有打开的流都会被关闭。
流一旦关闭后就不能执行任何操作
标准I/O – 读写流
流支持不同的读写方式:
读写一个字符:fgetc()/fputc()一次读/写一个字符
读写一行:fgets()和fputs()一次读/写一行
读写若干个对象:fread()/fwrite() 每次读/写若干个对象,而每个对象具有相同的长度
标准I/O – 按字符输入
下列函数用来输入一个字符:
#include <stdio.h>
int fgetc(FILE *stream);
int getc(FILE *stream); //fgetc和getc的功能是完全一样的,位要不同的是getc啊在标准C中被定义为一个宏,在使用的时候有一定的局限性;fgetc这里的“f”是function
int getchar(void);
成功时返回读取的字符;若到文件末尾或出错时返回EOF
getchar()等同于fgetc(stdin)
getc和fgetc区别是一个是宏一个是函数
标准I/O – fgetc – 示例
int ch;
ch = fgetc(stdin);
printf(“%c\n”, ch);
FILE *fp;
int ch, count = 0;
if ((fp = fopen(argv[1], “r”)) == NULL) {
perror(“fopen”); return -1;
}
while ((ch = fgetc(fp)) != EOF) {
count++;
}
printf(“total %d bytes\n”, count);
标准I/O – 按字符输出
下列函数用来输出一个字符:
#include <stdio.h>
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream); //这里的fputc和putc同fgetc和getc
int putchar(int c);
成功时返回写入的字符;出错时返回EOF
putchar©等同于fputc(c, stdout)
标准I/O – fputc – 示例
fputc(‘a’, stdout);
putchar(‘\n’);
FILE *fp;
int ch;
if ((fp = fopen(argv[1], “w”)) == NULL) {
perror(“fopen”); return