标准IO
标准IO与文件IO的区别:
文件IO: 直接调用内核提供的系统调用函数,头文件是unistd.h
标准IO:是间接调用系统调用函数,头文件是:stdio.h
三个缓存的概念(数组):
- 我们的程序中的缓存,就是你想从内核读写的缓存(数组) —用户空间的缓存。
- 每打开一个文件,内核在内核空间中也会开辟一 块缓存,这个叫内核空间的缓存。
文件IO中的写即是将用户空间中的缓存写到内核空间的缓存中。
文件IO中的读即是将内核空间的缓存写到用户空间中的缓存中。 - 标准IO 的库函数中也有一个缓存,这个缓存称为——库缓存
| 函数用途 | 标准IO函数1 | 标准IO函数2 |
|---|---|---|
| 文件打开关闭 | fopen | fclose |
| 文件读写 | fread | fwrite |
| 从文件中读取/输出字符串 | fgets | fputs |
| 获取、输出字符串 | gets | puts |
| 从文件中获取、输出字符 | fgetc | fputc |
| 终端输出输入一个字符 | getc | putc |
| 输出输入一个字符 | getchar | putcahr |
| 格式化输入输出、从文件 | fscanf | fprintf |
| 从字符串 | sscanf | sprintf |
| 从终端 | scanf | printf |
| 冲刷缓存区(全缓冲、含缓冲) | fflush | |
| 光标定位 | fseek ftell | rewind |
| 文件末尾 | feof |
库缓存
1)全缓冲 :全缓冲指的是系统在填满标准IO缓冲区之后才进行实际的IO操作;注意,对于驻留在磁盘上的文件来说通常是由标准IO库实施全缓冲。
读:fread 写:fwrite
2)行缓冲 :在这种情况下,标准IO在输入和输出中遇到换行符时执行IO操作;注意,当流涉及终端的时候,通常使用的是行缓冲。遇到换行符(\n)或写满缓存时,调用系统调用函数
读:fgets ,gets,printf,fprintf,sprintf
写:fputs,puts,scanf
3)无缓冲 :无缓冲指的是标准IO库不对字符进行缓冲存储;注意,标准出错流stderr通常是无缓冲的。
无缓存 stderr
fopen()
打开文件
头文件:#include <stdio.h>
函数原型:
FILE *fopen(const char *path, const char *mode);
返回值: 成功 返回 FILE *类型的指针指向你要打开文件
失败 返回NULL
函数参数:const char *path ---->你要打开文件的位置
const char *mode ---->文件权限
r 以只读的方式打开文件
r+ 以可读可写的方式打开文件
w 以只写的方式打开文件,如果文件存在就清空,如果文件不存在就创建
w+ 以可读可写的方式打开文件,如果文件存在就清空,如果文件不存在就创建
a 追加,如果文件不存在就新建
a+ 以读取和追加(文件末尾的写入),如果文件不存在,则创建它。
默认权限:666
fclose
头文件:#include <stdio.h>
int fclose(FILE* stream)
FILE* stream:文件描述符
调用成功返回0,失败返回EOF,并设置errmo,
在该文件被关闭之前,刷新缓存中的数据。如果标准I/O库已经为该流自动分配了一个缓存,则释放此缓存。
fgets 和fputs
行缓存的读写函数
char *fgets (char *s, int size, FILE *stream)
第一个参数:缓存,即读到哪里去。
第二个参数:读多少个字节。
第三个参数:从什么地方读。
返回值若成功则为s (缓存的地址),若已处文件尾端或出错则为null
int fputs(cqnst char *s,FILE *stream);
第一个参数:缓存,即写什么内容。
第二个参数:写到哪里去。
若成功则为非负值,若出错则为EOF -1。
fgetc和fputc
一个字符读写函数fgetc和fputc
int fgetc(FILE *fp)
功能:从文件中读取一个字符;
参数:文件流。
返回值:正确为读取的字符的ASCII码,到文件结尾或出错时返回EOF。
int fputc(int c, FILE *fp)
功能:写一个字符到文件中。
参数:第一个参数为要写的字符,第二个参数为文件流。
返回值:成功则返回输入的字符的ASCII,出错返回EOF。
gets和puts
char* gets(char* s);。
int puts(const char *s);
gets与fgets 的区别:。
gets()时不能指定 缓存的长度,这样就可能造成缓存越界(如若该行长于缓存长度),
写到缓存之后的存储空间中,从而产生不可预料的后果;。
gets()只能从标准输入中读;
get()与 fgets()的另一个区别是: gets0并不将新行符存入缓存中,fgets 将新行符存入缓存中;
puts与fgets的区别:
puts()只能向标准输出中写;
puts()与fputs()的另一个区别是: puts 输出时会添加一个新行符, fputs不会添加;
fflush
刷新缓存函数
fflush(FILE *fp)。
把库函数中的缓存的内容强制写到内核中。
fseek
头文件:#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
返回值:成功 返回0
失败 返回-1
注意:lseek返回值和fseek()返回值意思不一样
参数:FILE *stream FILE * 文件
long offset 偏移量
int whence 偏移的位置
SEEK_SET 文件的开头
SEEK_CUR 当前的位置
SEEK_END 文件的末尾
例子:fseek(filep1,0,SEEK_SET)
将文件的偏移设置为起始位置
ftell
long ftell(FILE *stream);
返回值:成功 返回文件当前位置距离文件开头的字节数
失败 返回-1
例子:long ftell(filep1);相当于fseek(filep1,0,SEEK_END);
rewind
void rewind(FILE *stream);//没有返回值
例子:void rewind(filp1)//等价于fseek(filep1,0,SEEK_SET)
将文件的偏移设置为起始位置
fprintf、printf、 sprintfs
行缓存函数
int fprintf(FILE *stream,"字符串格式”)
fprintf可以输出到文件中,也可输出到显示器,
printf只 能输出到显示器中。
int sprintf(str*,“字符串格式”)
输出内容到一个字符串中。
fefo
int feof(FILE *stream);。
功能:判断是否已经到文件结束。
参数:文件流。
返回值:到文件结束,返回为非0,没有则返回0。
ferror
int ferror(FILE *stream);
功能:判断是否读写错误!
参数:文件流。
返回值:是读写错误,返回为非0,不是则返回0.
cleareer
void clearerr(FILE *stream);
功能:清除流错误
参数:文件流。
fread和fwrite
全缓存函数
size t fread(void *ptr, size t size, size t nmemb, FILE *stream);
size t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:全缓存的读写函数
第一个参数buf:写的内容。
第二个参数size: 写的内容中,每一个单元所占的字节数。
第三个参数nmemb:写的内容中,有多少个单元数。
第四个参数stream: 写到哪里去。
总共写多少个字节,size *nmemb。
返回值:实际读写的单元数。
Linux操作系统支持的函数库分为:
函数库目录: /ib /us:/lib。
静态库,lixxx., 在编译时就将库编译进可执行程序中。
优点:程序的运行环境中不需要外部的函数库。
缺点:可执行程序大
动态库,又称共享库,lixxx.so, 在运行时将库加载到可执行程序中。
优点:可执行程序小。
缺点:程序的运行环境中必须提供相应的库。
静态库的制作:
1.生成目标文件: gcc -c file.c
2.静态 函数库创建命令ar
ar -cr libfile.a file.o
-c: create的意思
-r: replace的意思,表示当插入的模块file.o 已经存在libfile.a 中,则覆盖。反之ar显示一个错误消息。
操作静态库的几个实例:
情况1:如果从别处得 到一个静态库libunknown.a,想知道其中包含哪些模块。
命令: ar -t libunknowna
静态库的编译: gcc -o main main.c -L. -lfile
编译main.c就会把静态函数库整合进main.
其中:
L指定静态函数库的位置供查找,注意L后面还有,表示静态函数库在本目录下查找。
-l则指定了静态函数库名,由于静态函数库的命名方式是lib***.a,其中的lib和.a忽略。
删除libaddsub.a后main依然可以运行,因为静态库的内容已经整合进去了。
动态函数库的制作:
1.生成目标文件:gcc -c file.c
2.gcc -shared -fpic -o libfile.so file.o
-fpic:产生位置无关代码。
-shared:生成共享库。
用上述命令生成libaddsub.so动态函数库。
gcc -o out mainc L -l file
此时还不能立即./out,因为在动态函数库使用时,会查找/usr/lib /ib 目录下的动态函数库,而此时我们生成的库不在里边。
第一种方法:
libaddsub.so放到/usr/lib或/ib中去。
第二种方法,假设libfile. so在home/linux/file
export LD_ LIBRARY_ PATH=/home linux/addsub: $LD_ LIBRARY_ PATH
第三种方法:
在/et/ld.so.conf文件里加入我们生成的库的目录,然后/sbin/ldconfig。
/etc/ld.so.conf是非常重要的一个目录,里面存放的是链接器和加载器搜索共享库时要检查的目录,默认是从/ust/lib /lib中读取的,所以想要顺利运行,可以把我们库的目录加入到这个文件中并执行/sbin/ldconfig.