1,文件IO
1)open——打开或创建一个文件
open(char *,flag,mode)在fcntl.h文件中声明。
参数:
char * 包含有文件名和路径
flag 打开文件方式
mode 创建文件的权限
flag 内容
flag | 功能 |
O_RDONLY | 只读 |
O_WRONLY | 只写 |
O_RDWR | 读写 |
O_CREAT | 创建一个文件 |
O_EXCL | 如果使用O_CREAT是文件存在,则可返回错误消息。这一参数可测试文件是否存在 |
O_TRUNC | 打开文件(会删除已存在的内容) |
O_APPEND | 追加方式打开文件(不会删除已存在的内容) |
权限:文件权限 == mode&(~umask)
返回值:
成功:文件描述符(在一个进程中,为了区别每个文件),非负正整数,即文件的ID号;
出错:-1;
2)write————写
write (int fd,void *buf,size t count);
参数:
fd 向哪个文件去写
*buf 写什么内容
t 写多少个
返回值:
实际写的字节数
3)read————读
read (int fd,void *buf, size t count)
参数:
fd 从哪个文件去读
*buf 读什么内容
t 读多少个
返回值:
实际读的字节数
4)close————关闭文件
close(fd);
——————————————————————————————————————————————————————————————————
——————————————————————————————————————————————————————————————————
5) lseek ————调整读写位置指针
lseek(int fd,off_t offset,int whence);
头文件:sys/types.h unist.h;
参数:
fd : 要调整的文件的文件描述符
offset : 偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负;
whence : 当前位置的基点,有三个标志:
SEEK_SET : 当前位置为文件的开头,新位置为偏移量的大小(后移为正,前移为负)
SEEK_CUR : 当前位置为文件指针的位置,新位置为当前位置加偏移量
SEEK_END : 当前位置为文件的结尾,新位置为文件大小加偏移量的大小
返回值:
成功:文件当前的位置
出错:-1
******************************************************************************************************************************************************************************
文件IO:是直接调用内核提供的系统调用函数,头文件:unistd.h
标准IO:是间接点用系统调用函数,头文件: stdio.h
三个缓存:
1,程序中的缓存,就是你想从内核读写的缓存(数组)——用户空间的缓存
2,每打开一个文件,内核在内核空间中也会开辟一块缓存,——内核空间缓存
文件IO的 写 ——> 将用户空间的缓存写到内核空间的缓存中
文件IO的 读 ——>将内核空间的缓存读到用户空间的缓存
3,标准IO的库函数中也有一个缓存 —— 库缓存
2,标准IO
printf满足一定条件才能将库缓存的内容写到内核:遇到 ;库缓存写满时,会调用系统调用函数。(库缓存为1024字节)
1)fopen 打开
2) fclose 关闭 ,在关闭之前刷新缓存区,强制写入内核
3) fseek,rewind 位置指针
4) 读写函数较多(分三类:全缓存,行缓存,无缓存)
1) FILE *fopen (const char *path , const char *mode); 创建一个文件设置的权限为666,生成文件的权限为 666&(~umask)
返回值:FILE * 文件流指针 类似于文件IO中的文件描述符
FILE 定义 : struct_IO_FILE 在/usr/include/libio.h
包含读写缓存的首地址、大小、位置指针等
标准的输入流:stdin 0
标准的输出流:stdout 1
标准的出错流: stderr 2
参数:path 文件的位置
mode 相当于文件IO的flag (char * 字符串)
b : 二进制文件
r : 只读方式打开文件,文件必须存在
w/a : 只写方式打开文件,文件不存在则创建;
区别: w == O_TRUNC ; a == O_APPEND
+ : 读写方式打开文件,文件必须存在;
2)fcloes
3)读写函数
1, 行缓存 遇到新行符( ) 或写满缓存时,即调用系统调用函数
读: fgets,gets,printf,fprintf,sprintf
写: fputs,puts,scanf
2, 无缓存 只要用户调用这个函数,就会将其内容写到内核中
3,全缓存 只有写满缓存再调用系统调用函数
读 :fread
写 :fwrite
3.1 行缓存的读写函数fgets, fputs
char *fgets (char *s,int size , FILE *stream);
参数:
s : 缓存,即读到哪里去
size : 读多少字节
stream : 从什么地方读
返回值:
成功: s (缓存的地址)
已处于文件尾端或出错: null
int fputs (const char *s,FILE *stream);
参数:
s : 缓存。即写什么内容
stream : 写到哪里去
返回值:
成功:非负值
出错:EOF -1
3.2 fflush(FILE *fp)
把库函数的缓存内容强制写入内核(在fclose 中包含)
3.3 无缓存: stderr
stdout 行缓存
3.4 调整位置指针
fseek()
参数与lseek()一致,但返回值不同
返回值:
成功:0
失败:-1
rewind(FILE *fp) 用于设定流的文件位置指示为文件开始,该函数调用成功无返回值。
rewind() == (void) fseek(fp 0,SEEK_SET);
ftell(FEIL *fp)
用于取得当前的文件位置,调用成功则为当前文件位置指示,出错则为 -1L;
3.5 行缓存的读写函数 gets , puts
char *gets (char *s);
int puts (const char *s);
gets 与 fgets 的区别:
gets() 时不能指定缓存的长度,可能造成缓存越界,写到缓存之后的存储空间,产生不可预料的后果;
gets()只能从标准输入中读;
gets() 并不将新行符存入缓存,fgets()将新行符存入缓存;
puts 与 fputs 的区别:
puts()只能向标准输出中写;
puts() 输出是会添加一个新行符,fputs() 不会添加;
3.6 fprintf, printf, sprintf 行缓存的函数
int fprintf (FILE *stream,"字符串格式")
fprintf 可以输出到文件中,也可以输出到显示器 eg: fprintf(fp,"hello linux");
printf 只能输出到显示器
int sprintf (str *,"字符串格式")
输出内容到一个字符串中 eg: char buf[128] = 0; sprintf (buf,"hello linux");
3.7 一个字符的读写函数
int fgetc(FILE *fp) 将文件中的内容一个字符的输出到显示器,到文件结尾时返回EOF
功能: 从文件读取一个字符
参数: 文件流
返回值: 正确为读取到的字符;到文件结尾或出错时返回EOF
int fputc(int c, FILE *fp) 输入一个字符到文件中,成功则返回输入的字符,出错则返回EOF
功能:写一个特字符到文件中
参数:第一个参数为要写的字符,第二个为文件流
返回值: 正确为返回输入的字符,出错返回EOF
fputs 有缓存,但不是行缓存
——————————————————————————————————————————————————————————————————————————————
——————————————————————————————————————————————————————————————————————————————
3.8 feof 判断受否已经到文件结尾
int feof (FILE *stream);
参数:文件流
返回值:文件结束,返回非0;没有则返回0;
3.9 ferror 判断是否读写错误
int derror (FILE *stream);
参数:文件流
返回值: 是读写错误,返回非0;不是则返回0;
3.10 clearerr 清除流错误
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,xize_t nmemb,FILE *stream);
参数:
ptr: 写的内容
size: 写的内容中,每一个单元所占的字节数
nmemb: 写的内容中,有多少个单元
stream: 写到哪里去
总共所写的字节:size * nmemb
返回值: 实际读写的单元数
linux下静态库和动态库的制作与使用
- 静态库
libxxx.a , 在编译时就将库编译进可执行程序中。
优点:程序的运行环境中不需要外部的函数库
缺点:可执行程序大
- 动态库
又称共享库,libxxx.so ,在运行时将库加载到可执行程序中。
优点:可执行程序小
缺点:程序的运行环境中必须提供相应的库。
函数库目录:/lib /usr/lib
静态库的制作:
1,生成目标文件:gcc -c file.c
2,静态库创建命令 ar
ar -cr libfile.a file.o
-c : create
-r :replace ,表示当插入的模块 file.o 已经存在 libfile.a 中,则覆盖。反之 ar 显示一个错误消息
1)由源文件生成目标文件 gcc -c -o sub.o sub.c
2)把目标文件生成静态库 ar -cr -o libsub.a sub.o
3) gcc -o a main.c -L. -lsub . 代表当前目录;-lcub 默认libxxx.o
动态库制作:
1,生成目标文件 :gcc -c -o file.c
2,gcc -shared -fpic -o libfile.so file.o
-fpic : 产生位置无关代码
-shared: 生成共享库。
用上述命令生成 libsub.so 动态函数库
gcc -o out main.c -L. -lsub
此时还不能直接 ./out ,因为在动态函数库使用时,会查找/usr/lib /lib 目录下的动态函数库,而此时生成的库还不在里边
解决方法:
1) 把 libsub.so 放到 /usr/lib /lib 中去
2)假设 libsub.so 在/home/linux/file 中 环境变量的方式
export LD_LIBRARY_PATH = /home/linux/sddsub
LD_LIBRARY_PATH
3) 在 /etc/l.so.conf 文件中加入生成库的路径,然后 /sbin/ldconfig
/etc/ld.so.conf 时非常重要的一个目录,里面存放的时链接器和加载器搜索共享库时要检查的目录,默认是从 /usr/lib /lib 中读取,所以可以把库的目录假如这个文件并执行 /sbin/ldconfig
目录IO
#include <sys/types.h>
#inlcude <dirent.h>
目录IO | 文件IO |
opendir 只能打开目录 mkdir 创建目录 |
open |
readdir 读目录 | read |
rewinddir 调整指针位置 telldir seekdir |
rewind ftell fseek |
closedir 关闭目录 |
close |
1,opendir
DIR *opendir (const char *pathname);
参数:打开的目录及路径
返回值: 成功返回目录流指针,出错返回NULL
int mkdir (const char * path ,mode_t mode )
path: 为想创建的目录文件路径
mode: 为该目录的访问权限
返回值:若目录创建,则返回0;否则-1;
生成的目录权限仍和umask有关
2,readdir
struct dirent *readdir (DIR *dr)
参数:目录流指针
返回值:成功 则为 struct dirent 指针,瑞在目录尾或出错则返回NULL
struct dirent 定义在头文件 dirent.h中
此结构至少包括下列两个成员:
struct dirent
{
ino_t d_ino ; // inode 号
char d_name[NAME_MAX+1]; //文件名
}
3,rewinddir: 重置读取目录的位置为开头
void rewinddir(DIR *dr);
参数:目录流指针
long telldir(DIR *dirp) 读取当前指针的位置
参数:目录流指针
返回值:目录流当前位置
void seekdir(DIR *dirp,long loc);
类似于文件定位函数fseek(), 在目录流上设置下一个 readdir() 操作的位置
参数:目录流指针和偏移量