标准IO
标准IO由ISO C 标准的IO库,它处理了很多底层细节,比如合适的缓冲大小等等,因此更易于使用,但是也引入了一些其他问题。
流向
标准IO使用FILE对象关联流,流可以是面向宽字节的也可以是面向单字节的,当流初始化的时候是没有方向的,如果后面的IO操作是处理的宽字符集的,流变成面向宽字节的,如果哦是处理单字节的,流变成面向单字节,一旦流有了方向,不可改变,直到流被关闭,fwide可以设置流的方向,freopen可以清楚流的方向。
#include <wchar.h>
int fwide(FILE *stream, int mode);
如果mode值大于0,函数尝试设置流面向宽字节,如果mode值小于0,函数尝试流面向单字节,mode值等于0,函数返回当前流的方向。
如果流已经有了方向,fwide不会设置流的方向。返回没有出错返回,唯一的方法是在函数调用之前清除errno,在调用函数后检查errno。
在标准IO中,stdin,stdout,stderr 预定义指针对应STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO.
缓冲
标准IO操作时提供了合适的缓冲大小,不需要我们自己指定,同时提供了三种类型的缓冲:
1.全缓冲:只有当缓冲区满了之后才会进行IO操作
2.行缓冲 :遇到换行符或者缓冲区满了之后进行IO操作
3 无缓冲 :立即执行
一般来说面向交互式终端的是行缓冲,错误输出是无缓冲,其他情况是全缓冲的。通过setbuf和setvbuf可以改变默认行为:
#include <stdio.h>
void setbuf(FILE *restrict fp, char *restrict buf );
int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);
//Returns: 0 if OK, nonzero on error
setbuf函数如果buf设置为NULL,则是无缓冲,如果非NULL,必须是指向BUFSIZ长度的缓冲区地址,此时是全缓冲的。
setvbuf函数允许通过mode控制缓冲行为:
_IOFBF fully buffered
_IOLBF line buffered
_IONBF no buffered
buf一般使用NULL,这时size没有意义,这让标准库去关联缓冲,省去了不少麻烦。
注意:上面的函数必须在流打开后以及任何IO操作之前调用。
任何时候都可以通过fflush冲洗流:
#include <stdio.h>
int fflush(FILE *fp);
//Returns: 0 if OK, EOF on error
如果fp为NULL,函数冲洗所有输出流。
打开流:
#include <stdio.h>
FILE *fopen(const char *restrict pathname, const char *restrict type);
FILE *freopen(const char *restrict pathname, const char *restrict type,FILE *restrict fp);//在指定的FILE对象上打开流,如果流已经存在先关闭它,如果流有方向先清除方向
FILE *fdopen(int fd, const char *type);//将fd打开为标准流
//All three return: file pointer if OK, NULL on error
type取值如下:
r or rb 打开为只读
w or wb 创建为写或者清空
a or ab 追加或者创建为写或者打开为在尾端写
r+ or r+b or rb+ 读写
w+ or w+b or wb+ 清空或者创建为读写
a+ or a+b or ab+ 打开或者创建为尾端读写
当文件打开为读写的时候,有下面的限制:
写之后没有执行fflush,fseek,rwind,fsetpos不可以读
读之后没有执行fseek,fsetpos ,rewind不可以写。
关闭流:
#include <stdio.h>
int fclose(FILE *fp);
//Returns: 0 if OK, EOF on error
所有缓冲的输出数据都会在文件关闭之前冲洗,输入数据可能被丢弃。在进程正常关闭的时候,所有未写的缓冲数据都会被冲洗,并且流都会被关闭。
流读写:
1.一次一字符:
#include <stdio.h>
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);
int putc(int c, FILE *fp);
int fputc(int c, FILE *fp);
int putchar(int c);
//All three return: next character if OK, EOF on end of file or error
注意getc,fgetc getchar都是返回的字符是unsigned char强制转换为int,千万不要赋值给char变量。
2.一次一行:
#include <stdio.h>
char *fgets(char *restrict buf, int n, FILE *restrict fp);
char *gets(char *buf );//容易缓冲溢出,永远不要使用
//Both return: buf if OK, NULL on end of file or error
int fputs(const char *restrict str, FILE *restrict fp);
int puts(const char *str);
//Both return: non-negative value if OK, EOF on error
fputs向fp写入str,\0不会写入.
puts向标准输出写str,\0不会写入但是会换行。
3.二进制流:
#include <stdio.h>
size_t fread(void *restrict ptr, size_t size, size_t nobj,
FILE *restrict fp);
size_t fwrite(const void *restrict ptr, size_t size, size_t nobj,
FILE *restrict fp);
//Both return: number of objects read or written
如果fread返回值小于nobj说明出错或者达到文件尾,这时必须调用feof或者ferror判断。如果fwrite的返回值小于nobj说明出错。
流定向:
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, fpos_t *pos);
fseek设置流的pos,where:取值为SEEK_SET 表示文件头,SEEK_CUR当前位置,SEEK_END 文件尾。
ftell返回流的当前pos。
rewind将pos指向文件头相当于fseek(stream,0L,SEEK_SET)
fgetpos和fsetpos同ftell和fseek。
流格式化:
输出:
#include <stdio.h>
int printf(const char *restrict format, ...);
int fprintf(FILE *restrict fp, const char *restrict format, ...);
int dprintf(int fd, const char *restrict format, ...);
//All three return: number of characters output if OK, negative value if output error
int sprintf(char *restrict buf, const char *restrict format, ...);
//Returns: number of characters stored in array if OK, negative value if encoding error,最好不要用,用下面的
int snprintf(char *restrict buf, size_t n,const char *restrict format, ...);
//Returns: number of characters that would have been stored in array if buffer was large enough, negative value if encoding error
输入:
#include <stdio.h>
int scanf(const char *restrict format, ...);
int fscanf(FILE *restrict fp, const char *restrict format, ...);
int sscanf(const char *restrict buf, const char *restrict format, ...);
//All three return: number of input items assigned,EOF if input error or end of file before any conversion
说说format格式的转换类型,注意输入的有符号可能会转为无符号的。比如-1可能会扫描为4294967295存储在无符号数中。
转换类型 含义
c 字符
s 字符串
[ 列出的字符串,以]结尾
[^ 非列出的字符串 ,以]结尾
stream对象转为FD:
int fileno(FILE *stream);//函数不会失败
临时文件:
#include <stdio.h>
char *tmpnam(char *ptr);
//Returns: pointer to unique pathname
FILE *tmpfile(void);
//Returns: file pointer if OK, NULL on error
tmpnam使用ptr产生临时文件,如果ptr为NULL,库会使用静态数组存储名字,多次调用静态数组将被覆盖。成功返回唯一的路径,失败返回空。当参数为NULL时该函数不是线程安全的,应该使用tmpnam_r替代。
tmpfile产生一个二进制临时文件,流关闭或者进程结束后,文件自动删除。
UNIX还提供了下面函数生成临时文件:
#include <stdlib.h>
char *mkdtemp(char *template);
//Returns: pointer to directory name if OK, NULL on error
int mkstemp(char *template);
//Returns: file descriptor if OK, −1 on error
mkdtemp相当于mkdir(template,S_IRUSR|S_IWUSR|S_IXUSR)
mkstemp相当于create(template,S_IRUSR|S_IWUSR)
注意:使用这两个函数创建的临时文件不会自动删除,需要我们自己删除。由于tmpnam和tempnam不是原子操作,应该使用tmpfile和mkstemp。
标准IO的更多相关文章
- 深究标准IO的缓存
前言 在最近看了APUE的标准IO部分之后感觉对标准IO的缓存太模糊,没有搞明白,APUE中关于缓存的部分一笔带过,没有深究缓存的实现原理,这样一本被吹上天的书为什么不讲透彻呢?今天早上爬起来赶紧找了 ...
- [APUE]标准IO库(下)
一.标准IO的效率 对比以下四个程序的用户CPU.系统CPU与时钟时间对比 程序1:系统IO 程序2:标准IO getc版本 程序3:标准IO fgets版本 结果: [注:该表截取自APUE,上表中 ...
- [APUE]标准IO库(上)
一.流和FILE对象 系统IO都是针对文件描述符,当打开一个文件时,即返回一个文件描述符,然后用该文件描述符来进行下面的操作,而对于标准IO库,它们的操作则是围绕流(stream)进行的. 当打开一个 ...
- 标准io与文件io
A: 代码重复: 语句块1: while(判断) { 语句块2: 语句块1: } 上面可以改写为: while(1) { 语句块1: if(判断) break: 语句块2: } B: 标准IO和文件I ...
- linux标准IO缓冲(apue)
为什么需要标准IO缓冲? LINUX用缓冲的地方遍地可见,不管是硬件.内核还是应用程序,内核里有页高速缓冲,内存高速缓冲,硬件更不用说的L1,L2 cache,应用程序更是多的数不清,基本写的好的软件 ...
- 【linux草鞋应用编程系列】_1_ 开篇_系统调用IO接口与标准IO接口
最近学习linux系统下的应用编程,参考书籍是那本称为神书的<Unix环境高级编程>,个人感觉神书不是写给草鞋看的,而是 写给大神看的,如果没有一定的基础那么看这本书可能会感到有些头重脚轻 ...
- 文件IO函数和标准IO库的区别
摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lsee ...
- linux标准io的copy
---恢复内容开始--- 1.linux标准io的copy #include<stdio.h> int main(int argc,char **argv) { if(argc<3) ...
- (九)errno和perror、标准IO
3.1.6.文件读写的一些细节3.1.6.1.errno和perror(1)errno就是error number,意思就是错误号码.linux系统中对各种常见错误做了个编号,当函数执行错误时,函数会 ...
- 标准IO的简单应用,动静态库,读取系统时间并打印,模拟ls -l功能
2015.2.27星期五,小雨 标准IO实现的复制功能: #include <stdio.h>#include <errno.h> #define N 64 int main( ...
随机推荐
- 【原创】通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 ‘incorrect string value: '\xF0...
这篇blog重点在解决问题,如果你对字符编码并不是特别了解,建议先看看 < [原创]通俗易懂地解决中文乱码问题(1) --- 跨平台乱码 >. 当然,如果只是针对解决这个Mysql插入报错 ...
- PHP 增删改查 import!!
主页面 <h1>主页面family</h1> <table width="100%" border="1px" cellpaddi ...
- dojo 九 effects dojo/_base/fx 和 dojo/fx
官方教程:Dojo Effects这里讲学习一下dojo如何实现淡入.淡出.滑动等效果.实现这些特殊的效果有两个包 dojo/_base/fx 和 dojo/fx.dojo/_base/fx 中提供了 ...
- find a filename from a filehandle in Perl
my $filename='/tmp/tmp.txt';open my $fh, '>', $filename;my $fd = fileno $fh;print readlink(" ...
- in command-line: path> mvn eclipse:clean path> mvn -Dwtpversion=1.5 eclipse:eclipse path> mvn eclipse:eclipse in eclipse: Project / clean...
原因:tomcat已经启动了 2007-10-9 12:26:16 org.apache.coyote.http11.Http11AprProtocol init严重: Error initializ ...
- Mybatis返回插入的主键
在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数:如果业务层需要得到记录的主键时,可以通过配置的方式来完成这个功能 情景一:针对自增主键的表,在插入时不 ...
- 51nod1262 扔球
相关讨论里的答案:(by mint_my ) 1.反弹n次,那起点S,每次反弹点,终点S共连接n+1条边,那么原问题变为从S走n+1条边回到S,为令n=n+12.设步长为a条边,gcd(a,n)==1 ...
- 51nod1189 阶乘分数
(x-n!)(y-n!)=n!2 ans=t[n]+1.t表示的是n!2的小于n!的约数个数.n!2=p1a1*p2a2*p3a3...t[n]=(a1+1)*(a2+1)...-1 /2; 2对于n ...
- java基础 (记事本编写hello world,path,classpath,java的注释符)
一:java的基本信息 jre 是指java运行环境,jdk 是指 java 开发工具集(并且里面是自带有jre运行环境的) jvm是指java的虚拟机 java的源代码的后缀名是 .java (例如 ...
- 解决Eclipse快捷键被其他软件占用
做为一个java攻城狮,eclipse是我最常用的攻城设备,eclipse快捷键 极大的提高了我的开发效率!!!! 前段时间升级了一下我的战斗装备——给电脑的系统盘换成了一个固态硬盘,因此需要重装系统 ...