1、标准IO
stdin:标准输入,针对键盘
stdout:标准输出,针对屏幕
stderr:标准出错,针对屏幕
三个都是FILE类型的结构体指针,成为流指针
1.1标准C的IO缓存类型
1.全缓存
要求填满整个缓冲区后才进行I/O系统调用操作,对于磁盘文件通常使用全缓存访问。
2.行缓存
涉及一个终端时(例如标准输入和标准输出),使用行缓存;
行缓存满自动溢出;碰到换行符自动输出。
3.无缓存
标准错误流stderr通常是不带缓存的,这使得错误信息能够尽快的显示出来。
1.2文件I/O系统调用
1常用函数
打开文件:open()
创建文件:create()
关闭文件:close()
读取文件:read()
写入文件:write()
文件定位:lseek()
图1 标准IO与系统IO的位置
2、标准IO的缓冲机制
缓冲机制一般分为三种:全缓冲、行缓冲和无缓冲。
(1)全缓冲:输入或者输出缓冲区被填满就会进行实际的I/O操作;
(2)行缓冲:输入或者输出缓冲区遇到换行符时就会进行实际的I/O 操作;
(3)无缓冲:没有缓冲区,数据会立即读入内存或者输出到文件和设备上。
windows系统下是默认没有全缓冲的,只有行缓冲,如果需要设置全缓冲,则需调用setbuf或者setvbuf函数。
函数原型:void setbuf(FILE *fp, char *buf)
buf的大小至少为BUFSIZ大小,即512,或者为BUFSIZ的倍数。
函数原型:void setvbuf(FILE *fp, char *buf, int type, unsigned size)
buf的大小至少为2,type的类型为:_IOFBF表示全缓冲,_IOLBF表示行缓冲,_IONBF表示无缓冲,如果设置为无缓冲,则会忽略buf和size的值。
int c;
static char buf[10];
setvbuf(stdout, buf, _IOFBF, 10);
while ((c=getchar())!=EOF)
{
putchar(c);
}
在上述代码中,如果缓冲区的 大小达到10个字节后就会进行实际的I/O输出,并且需要用static关键字定义,或者将buf声明为外部的全局变量,或者使用malloc去开辟数组空间而不去释放内存。
3、目录操作
文件IO是系统调用,标准IO是c语言库函数
文件IO使用文件描述符,标准IO使用FILE*文件流
文件IO不带缓冲,标准IO带缓冲
文件IO多用于操作设备文件,标准IO一般多用于操作普通文件
b. 内核中有一个文件表项,保存了已经打开的文件的相关信息
c. 文件IO要用文件描述符对文件进行操作
文件描述符是一个非负整数,stdin->0, stdout->1, stderr->2
d. 文件操作步骤
[创建]打开文件
操作文件 read/write/ioctl
关闭文件
e. 相关的函数
打开文件
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
参数 :
pathname : 文件名
flags : 打开方式,必须包含以下三个中的一个O_RDONLY,O_WRONLY,O_RDWR
O_CREAT : 创建文件
O_TRUNC : 创建文件时,清空文件内容
O_NONBLOCK or O_NDELAY :非阻塞打开
O_EXCL : 文件存在的情况下创建该文件,会打开失败
mode : 权限,在创建文件的时候,需要指明权限。一般用8进制表示。
返回值:成功时,返回非负整数;失败时,返回-1。
读文件内容
size_t read( int fd, void * buf, size_t size);
参数:
fd : 文件描述符,是open的返回值
buf : 读到的数据保存在buf中
size : 准备读取的数据长度
返回值:成功时,返回读到的字节数;失败时,返回-1。
写内容到文件中
size_t write( int fd, const void * buf, size_t size);
参数:
fd : 文件描述符,是open的返回值
buf : 准备写的数据保存在buf中
size : 准备写的数据长度
返回值:成功时,返回写入的字节数;失败时,返回-1。
关闭文件
int close( int fd );
参数:
fd : 文件描述符,是open的返回值
返回值:成功时,返回0;失败时,返回-1。
2. 空洞文件
新建文件,内容是空的,但大小已经占位。
long lseek( int fd, int offset, int whence );
==> fseek() + ftell();文件属性
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
ls是一个可执行文件,在/bin目录; ls -l 本质是运行一个文件,这个文件名叫"ls","-l"相当于给ls传的参数
./a.out 1.txt目录操作
目录是一种特殊的文件,它是用于存放其它文件的。
操作步骤:
打开目录
操作目录 读目录、改名、新建文件、删除文件
关闭目录
相关的函数
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
struct dirent *readdir(DIR *dirp);
int closedir(DIR *dirp);
int rename(const char *oldpath, const char *newpath);
int remove(const char *pathname);
静态库和动态库
什么是库:可执行代码的二进制形式。
特点:
什么时候链接
静态库在编译时链接
动态库在运行时链接
在运行程序时,是否需要库
静态库不需要
动态库需要
是否需要移植
静态库不需要移植
动态库需要进行移植
可执行文件size的大小
静态库编译后的文件size大
动态库编译后的文件size小
库文件升级
静态库需要重新编译可执行文件
动态库需要移植新的库,不需要重新编译
制作和使用
例:将hello.c制作成静态库,main.c调用hello.c中的函数
静态库
1. 先将库对应的.c编译成.o文件
gcc -c hello.c -o hello.o
2. 将.o文件打包成静态库[静态库的前缀是lib,扩展名.a]
ar crs libmyLib.a hello.o
3. 在编译main.c时,链接静态库
gcc main.c -lmyLib -L./ -o main
4. 运行可执行文件,进行测试
./main
动态库
1. 先将库对应的.c编译成.o文件
gcc -fPIC -Wall hello.c -o hello.o
2. 将.o文件打包成动态库[动态库的前缀是lib,扩展名.so]
gcc -shared hello.o -o libHello.so
3. 编译main.c时,链接动态库
gcc main.c ./libHello.so -o main