标准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: ?le 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 ?le 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 ?le 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 ?le 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: ?le 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: ?le 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。

时间: 2024-08-06 09:16:20

标准IO的相关文章

内核IO和标准IO

对于文件的读写操作函数在执行的空间来分,可以分为内核IO(主要在内核中运行)和标准IO(主要在用户空间中运行). 内核IO需要自己创建和管理缓存,而标准IO是自动分类缓存,一般来说,内核IO的效率高于标准IO,但是差距不是很大,考虑移植性,还是建议使用标准IO(只要是支持标准C语言就支持标准IO). 无论是标准IO还是内核IO都是对文件的信息,读写文件的指针进行记录的,调用相应的函数可以进行文件信息的读取和指针的修改. 以下为IO相关的函数的头文件,使用,参数,返回值的说明 linux C语言I

第一天20150829:标准IO 和 系统IO -----stdio and sysio

IO 的实现包括两种实现: 1.stdio标准IO 2.sysio系统IO IO的两种实现方式正常都可以使用.但是,在使用的过程中优先使用stdio标准IO. 首先要了解这两种实现的原理: 1.sysio系统IO:我们作为USER 要与内核对话,那么系统为我们提供了一个sysio,可以直接对话KERNAL. 那么问题就产生了:如果USER使用的平台环境不一样(有的人有linux,有的人用windows),那么由于KERNAL不一样,那么提供给USER的sysio也会不一样 2.所以引申出来一个标

标准IO的简单应用,动静态库,读取系统时间并打印,模拟ls -l功能

2015.2.27星期五,小雨 标准IO实现的复制功能: #include <stdio.h>#include <errno.h> #define N 64 int main(int argc, char *argv[]){ int n; char buf[N]; FILE *fps, *fpd; if(argc < 3) { printf("usage : %s <src_file><dst_file>\n",argv[0]);

C++ Primer 读书笔记: 第8章 标准IO库

第8章 标准IO库 8.1 面向对象的标准库 1. IO类型在三个独立的头文件中定义:iostream定义读写控制窗口的类型,fstream定义读写已命名文件的类型,而sstream所定义的类型则用于读写存储在内存中的string对象.在fstream和sstream里定义的美中类型都是从iostream头文件中定义的相关类型派生而来. 2. 流对象不能复制,因此不能存储在vector容器中 3. 形参或返回类型也不能为流类型.如果需要传递或返回IO对象,则必须传递或返回指向该对象的指针或引用.

标准IO与文件IO 的区别【转】

本文转载自:http://blog.sina.com.cn/s/blog_63f31f3401013jrn.html 先来了解下什么是标准IO以及文件IO. 标准IO:标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具有一定的可移植性.标准IO库处理很多细节.例如缓存分配,以优化长度执行IO等.标准的IO提供了三种类型的缓存. (1)全缓存:当填满标准IO缓存后才进行实际的IO操作.         (2)行缓存:当输入或输出中遇到新行符时,标准

Linux学习之标准IO 管道 033_7

默认输入为键盘,标准输出为显示器,错误输出为显示器 把标准输出和错误输出重定向到文件: command operator filename operators: >:标准输出重定向 :把ls -R的输出重定向到文件 2>:错误输出重定向 &>:将正确和错误的输出都重定向 同时将正确和错误信息分别导入到不同文件: 以上默认覆盖,如果在文件末尾添加则用>>s 把错误输出重定向到空设备,也就是忽略错误信息 管道: 将前面一条命令执行的结果作为后面一条命令的输入 如: ls

[APUE]标准IO库(下)

一.标准IO的效率 对比以下四个程序的用户CPU.系统CPU与时钟时间对比 程序1:系统IO 程序2:标准IO getc版本 程序3:标准IO fgets版本 结果: [注:该表截取自APUE,上表中"表3-1中的最佳时间即<程序1>","表3-1中的单字节时间指的是<程序1>中BUFSIZE为1时运行时间结果",fgetc/fputc版本程序这里没放出] 对于三个标准IO版本的每一个其用户CPU时间都大于最佳read版本,因为每次读一个字符

标准IO与文件IO 的区别

1.定义 标准IO:标准I/O是ANSI C建立的一个标准I/O模型,是一个标 准函数包和stdio.h头中的定义,具有一定的可移植性.标准IO库处理很多细节.例如缓存分配,以优化长度执行IO等.标准的IO提供了三种类型的缓存.(1)全缓存:当填满标准IO缓存后才进行实际的IO操作.(2)行缓存:当输入或输出中遇到新行符时,标准IO库执行IO操作.(3)不带缓存:stderr就是了. 文件IO:文件IO称之为不带缓存的IO(unbuffered I/O).不带缓存指的是每个read,write都

linux标准io的copy

---恢复内容开始--- 1.linux标准io的copy #include<stdio.h> int main(int argc,char **argv) { if(argc<3) { printf("use:mycp file1 file2\n"); return -1; } FILE *src=fopen(argv[1],"r");//打开源文件 if(src==NULL) { printf("no file!\n");