目录
二/文件操作API:
1、open函数
使用:man 2 open 查询
功能:打开文件
//包含的头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//函数原型
int open(const char *pathname, int flags);/*常用*/
int open(const char *pathname, int flags, mode_t mode);/*不常用,不用了解*/
/*
//参数
+pathname:字符串,是文件名,包含绝对路径,如果没有绝对路径,则默认是当前路径
+flags:以何种方式打开文件
++常用包括:
O_CREAT:如果文件不存在则创建,存在则打开
O_RDONLY:只读打开
O_WRONLY:只写打开
O_RDWR:可读可写打开文件
O_APPEND:追加
O_NOCTTY:如果文件指向终端设备,不要将其用作控制终端
O_TRUNC:如果文件存在,并且是以只读或者读写方式打开,则将其长度截断为0
O_EXCL:文件存在的话,则出错,并且返回-1
+mode:添加权限
//返回值:成功返回文件句柄,失败返回-1;
*/
2、close函数
功能:关闭文件
//包含的头文件
#include <unistd.h>
//函数原型
int close(int fd);
/*
//参数
+fd:需要关闭的文件的句柄
//返回值:成功返回0,失败返回-1;
*/
3、write函数
功能:将buf数组的内容写入count个字节到fd文件中
//包含的头文件
#include <unistd.h>
//函数原型
ssize_t write(int fd, const void *buf, size_t count);
/*
//参数
+fd:需要写入的文件的句柄
+buf:数组
+count:需要写入的字节数
//返回值:成功返回实际写入的字节数,失败返回-1;
*/
4、read函数
功能:将fd文件的内容读出count个字节到buf数组中
//包含的头文件
#include <unistd.h>
//函数原型
ssize_t read(int fd, void *buf, size_t count);
/*
//参数
+fd:需要读出的文件的句柄
+buf:数组
+count:需要读出的字节数
//返回值:成功返回实际读出的字节数,失败返回-1;
*/
争对write和read系统调用,可以读写文件描述符为0 (宏:STDIO),1(宏:STDOUT),2的文件(宏:STDERR),
0是标准输入(先到库缓存)
#include <unistd.h>
int main()
{
char buff[20] = {0};
read(0, buff, 10);
write(1,buff, 10);
return 0;
}
结果:执行./a.out后,等待输入,程序读取前十个字节,然后write输出到屏幕上,然后结束进程,输入缓冲区还剩下字符d niaho,就当作shell命令执行,最后找不到命令
#include <unistd.h>
int main()
{
write(1, "hello world\n",sizeof("hello world\n"));
return 0;
}
结果:执行./a.out在屏幕上输出hello world并且换行
2是标准错误输出(直接到系统缓存)
5、lseek函数
功能:读文件的时候,移动光标
//包含的头文件
#include <sys/types.h>
#include <unistd.h>
//函数原型
off_t lseek(int fd, off_t offset, int whence);
/*
//参数
+fd:操作的文件
+offset:偏移量
+whence:
++SEEK_SET:以当前offset为光标位置,比如offset=0,则光标定位到文件首(SEEK_SET模式下offset不能为负数)
++SEEK_CUR:以当前光标所在的位置偏移offset多个位置,正数向右偏移,负数向左偏移
++SEEK_END:将光标定位到文件尾后再偏移offset多个位置,正数向右偏移,负数向左偏移
//返回值:成功返回光标距离文件首的字节,失败返回-1;
*/
//以上API是linux下的系统调用函数接口,此外,标准C库里边也有类似的函数,如下fopen,fclose,fread,fwrite等
显然,C库的函数移植性更好
6、fopen函数
功能:打开文件输入输出流
//包含的头文件
#include <stdio.h>
//函数原型
FILE *fopen(const char *pathname, const char *mode);
/*
//参数
+pathname:字符串,是文件名,包含绝对路径,如果没有绝对路径,则默认是当前路径
+mode:以何种方式打开文件
++包括:
r:只读方式打开,文件必须存在
r+:可读写,文件必须存在
w:只写,存在则长度清零,不存在则建立文件
w+:可读写,存在则长度清零,不存在则建立文件
a:附加方式打开,只写,不存在则建立,存在则追加,EOF符保留
a+:附加方式打开,可读写,不存在则建立,存在则追加,EOF符不保留
rb+:打开二进制文件,可读写
rt+:打开文本文件,可读写
wb:打开二进制文件,只写
wb+:打开或建立二进制文件,可读写
wt+:打开或建立文本文件,可读写
ab+:打开二进制文件,可读写,写的数据加载文件末尾
at+:打开文本文件,可读写,写的数据加在文件末尾
//返回值:FILE是一个结构体,包含文件相关的个各种信息。成功返回指针,失败返回NULL;
*/
7、fclose函数
功能:关闭该stream指向文件的IO流
如果库缓冲区还剩下数据,则将剩余数据传到系统缓冲区。
//包含的头文件
#include <stdio.h>
//函数原型
int fclose(FILE *stream);
/*
//参数
+stream:文件指针,关闭该文件的IO流
//返回值:成功返回0,失败返回EOF
*/
8、fread和fwrite函数
功能:fread:从stream指向的文件读nmemb多次size字节到ptr缓冲区
fwrite:从文件ptr缓冲区写nmemb多次size字节到stream指向的文件
//包含的头文件
#include <stdio.h>
//函数原型
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);
/*
//参数
+ptr:缓冲区指针
+size:一次读写字节数
+nmemb:读写次数
+stream:读写目标文件IO流
//返回值:成功返回实际读写次数(并非nmemb),失败返回-1
*/
扩展:
1 #include <stdio.h>
2
3 int main()
4 {
5 printf("nihao");
6 fwrite("hello1",6, 1, stdout);
7 fwrite("hello2",6, 1, stderr);
8 while(1);
9 return 0;
10 }
执行以上代码,就可以知道只输出hello2,然后进入while(1)循环。“nihao”和“hello1”并不会打印到屏幕,而是还在库缓冲区。
9、fseek函数
功能:类似移动光标,实际是改文件内部指针位置
//包含的头文件
#include <stdio.h>
//函数原型
int fseek(FILE *stream, long offset, int whence);
//参数参考五、lseek系统调用,简直一样//
/*
//参数
+stream:操作的文件
+offset:偏移量
+whence:
++SEEK_SET:以当前offset为光标位置,比如offset=0,则光标定位到文件首(SEEK_SET模式下offset不能为负数)
++SEEK_CUR:以当前光标所在的位置偏移offset多个位置,正数向右偏移,负数向左偏移
++SEEK_END:将光标定位到文件尾后再偏移offset多个位置,正数向右偏移,负数向左偏移
//返回值:成功返回0,失败返回-1;
注意:返回值跟lseek不一样
*/
10、fuptc函数族
fputs,fputs,putchar,puts:当遇到‘\n’或者库缓冲区满(1024字节)的时候,才将库缓冲区的数据送到系统缓冲区,进行数据传输,实现打印或者写入文件。否则一直存在库缓冲区,不会显示也不会写入到文件,只有等待文件关闭的时候(参考fclose函数),才将剩余的数据传给系统缓冲区。另外可以调用函数fflush,强制性将库缓冲区的数据传给系统缓冲区,实现打印到屏幕或者写到文件。
//包含的头文件
#include <stdio.h>
//函数原型
//1.将字符c写入文件流stream
int fputc(int c, FILE *stream);
//2.将字符串s写入文件流stream
int fputs(const char *s, FILE *stream);
//3.Putc()等价于fputc(),不同之处在于它可以作为一个宏来实现流不止一次。(不同之处不用看)
int Putc(int c, FILE *stream);
//4.将字符c输出到屏幕
int putchar(int c);
//5.将字符串s输出到屏幕
int puts(const char *s);
//返回值:
fputc(), putc(), and putchar() return the character written as an unsigned char cast to an
int or EOF on error.
puts() and fputs() return a nonnegative number on success, or EOF on error.
nonnegative:正数
11、fflush函数
参考10
功能:将库缓冲区的数据强制传输到系统缓冲区
//包含的头文件
#include <stdio.h>
//函数原型
int fflush(FILE *stream);
12、getc族函数
//包含的头文件
#include <stdio.h>
//函数原型
//读一个字符,返回该字符,在文件的结尾或者错误返回EOF
int fgetc(FILE *stream);
//读stream到s缓冲区size字节,成功返回s指针,失败返回NULL
char *fgets(char *s, int size, FILE *stream);
int getc(FILE *stream);//读文件stream一个字符
int getchar(void);//读键盘一个字符
int ungetc(int c, FILE *stream);
/*//返回值:
fgetc(), getc(), and getchar() return the character read as an unsigned char cast to an
int or EOF on end of file or error.
fgets() returns s on success, and NULL on error or when end of file occurs while no char‐
acters have been read.
ungetc() returns c on success, or EOF on error.
*/
13、rewind函数
将光标回到文件头;rewind(fd)等价于fseek(fd,0,SEEK_SET);
void rewind(FILE *stream);
14.feof,ferror函数
#include <stdio.h>
void clearerr(FILE *stream);//清除错误标志
int feof(FILE *stream);//文件是否结束
int ferror(FILE *stream);//文件是否出错
int fileno(FILE *stream);//不重要
15.静态动态库
add.c
int add(int a,int b)
{
return (a+b);
}
main.c
#include <stdio.h>
int add(int a,int b);
int main()
{
int x = 1,y = 5;
printf("he = %d \n",add(x, y));
return 0;
}
①、静态库:
gcc add.c -c -o add.o //生成.o文件(与文件路径有关)
ar -cr -o libadd.a add.o //生成add静态库文件,libadd.a中add才是名字,lib是前缀表示库,.a是后缀表示静态库
gcc main.c -L. -ladd //生成a.out可执行文件,-L.表示在当前文件找,-ladd表示链接上add库
./a.out //执行a.out文件
②、动态库:
//生成.o文件(与文件路径无关,)
gcc -c -fpic add.c
//生成add动态库文件,libadd.so中add才是名字,lib是前缀表示库,.so是后缀表示动态库
gcc -shared add.o -o libadd.so
gcc main.c -ladd -L. //生成a.out
./a.out //执行
但是运行时会显示无法找到该动态库:
解决方法一:
配置环境变量:LD_LIBRARY_PATHadd
export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
注意pwd上的两个``是Tab键上的那个点,不是‘’。
但是export方式在重启终端后失效
**方法二:**将libadd.so复制到/usr/lib下
sudo cp libadd.so /usr/lib
复制完后执行a.out,然后删除/usr/lib目录下的libadd.so(学习而已,不要乱加东西到库里面)
**说明:**库要和头文件一起使用,因为没有头文件,别人不知道这个库中有哪些函数,就无法使用。
库可以看作是将头文件里面定义的函数进行实际实现的代码。
在使用gcc编译的时候,加上参数 -l xxx -L (库文件的目录)
比如说 gcc main.c -ladd -L.,其中add表示使用libadd.so的库文件,命令中只需要写库名称省略前缀后缀。