一.文件编程
1.文件的打开、关闭与创建
1.1 相关Linux API
#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);
int close(int fd);
int creat(const char *pathname, mode_t mode);
其中:
1、char* pathname 是文件所在位置,一个字符串
2、flag 主要有以下主要的类型:
- O_RDONLY 只读
- O_WRONLY 只写
- O_RDWR 可读可写
- O_CREAT 创建一个文件
- O_EXCL 若文件存在,则报错
- O_APPEND 对文件的写操作时,新内容写在原数据后面
- O_TRUNC 对文件的写操作时,把原内容删除,再写
3、mode表示O_CREAT创建文件时新文件的权限
读-4 写-2 执行-1
举个例子:
0600 可读可写
0400 可读不可写
0200 可写不可读
返回值:open函数读取成功:返回正数,错误为-1;
1.2 文件的打开与关闭
1.2.1 普通open
int open(const char *pathname, int flags);
举个例子:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd=open("./file1",O_RDWR);
printf("fd=%d\n",fd);
return 0;
}
当前目录:
CLC@Embed_Learn:~/Linux_review/File_programming$ ls
a.out demo1.c file1
运行结果(打开成功):
CLC@Embed_Learn:~/Linux_review/File_programming$ ./a.out
fd=3
运行结果(打开失败):
CLC@Embed_Learn:~/Linux_review/File_programming$ ls
a.out demo1.c
CLC@Embed_Learn:~/Linux_review/File_programming$ ./a.out
fd=-1
1.2.2 有权限的open
int open(const char *pathname, int flags, mode_t mode);
举个例子:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd=open("./file1",O_RDWR,0600);
printf("fd=%d\n",fd);
return 0;
}
当前目录:
CLC@Embed_Learn:~/Linux_review/File_programming$ ls
a.out demo1.c demo2.c file1
运行结果(打开成功):
CLC@Embed_Learn:~/Linux_review/File_programming$ ./a.out
fd=3
运行结果(打开失败):
CLC@Embed_Learn:~/Linux_review/File_programming$ ls
a.out demo1.c demo2.c
CLC@Embed_Learn:~/Linux_review/File_programming$ ./a.out
fd=-1
1.2.3 close函数
close(fd);
1.3 文件的创建
1.3.1 以带权限的open函数实现
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd=open("./file1",O_RDWR,0600);
if(fd ==-1)
{
printf("open failed!\n");
open("./file1",O_RDWR|O_CREAT,0600);
printf("create success!\n");
}
//printf("fd=%d\n",fd);
return 0;
}
程序执行前:(没有file1)
CLC@Embed_Learn:~/Linux_review/File_programming$ ls
a.out demo1.c demo2.c
程序执行后:(生成了file1)
CLC@Embed_Learn:~/Linux_review/File_programming$ ls
a.out demo1.c demo2.c file1
1.3.2 以creat函数实现
int creat(const char *pathname, mode_t mode);
举个例子:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
creat("./createFile",0600);
return 0;
}
程序执行前:(没有creatFile)
CLC@Embed_Learn:~/Linux_review/File_programming$ ls
a.out demo1.c demo2.c demo3.c file1
程序执行后:(生成了creatFile)
CLC@Embed_Learn:~/Linux_review/File_programming$ ls
a.out createFile demo1.c demo2.c demo3.c file1
查看一下权限:
CLC@Embed_Learn:~/Linux_review/File_programming$ ls -l
total 24
-rwxr-xr-x 1 CLC book 8378 Sep 14 23:11 a.out
-rw------- 1 CLC book 0 Sep 14 23:13 createFile
-rw-r--r-- 1 CLC book 342 Sep 14 22:31 demo1.c
-rw-r--r-- 1 CLC book 467 Sep 14 22:56 demo2.c
-rw-r--r-- 1 CLC book 311 Sep 14 23:13 demo3.c
-rw------- 1 CLC book 0 Sep 14 22:58 file1
createFile 的权限为-rw 可读可写 印证了0600
2.文件的读写
2.1 相关Linux API
#include <unistd.h>
//读:
ssize_t read(int fd, void *buf, size_t count);
//写:
ssize_t write(int fd, const void *buf, size_t count);
其中:
- fd 代表文件描述符
- buf 字符串缓存
- count 需要读、写的字节数量
- 返回值:成功为读、写的字节个数,失败为-1
2.2 文件的读取 read
ssize_t read(int fd, void *buf, size_t count);
举个例子:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* buf;
buf=(char*)malloc(128);
int fd;
fd=open("./TestFile",O_RDWR|O_CREAT,0600);
read(fd,buf,128);
printf("buf=%s\n",buf);
return 0;
}
TestFile的内容:
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
~
~
"TestFile" 1L, 121C
读出来的结果:
CLC@Embed_Learn:~/Linux_review/File_programming$ ./a.out
buf=123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
2.3 文件的写入 write
ssize_t write(int fd, const void *buf, size_t count);
举个例子:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* buf="William is handsome";
int fd;
fd=open("./TestFile2",O_RDWR|O_CREAT,0600);
printf("open success!fd=%d\n",fd);
write(fd,buf,strlen(buf));
close(fd);
return 0;
}
TestFile2的内容:
William is handsome
~
~
~
~
~
"TestFile2" 1L, 20C
2.4 文件的读写
将上述二者结合一下:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* buf="William is handsome";
char* readBuf;
readBuf=(char*)malloc(sizeof(buf));
int fd;
fd=open("./TestFile2",O_RDWR|O_CREAT,0600);
printf("open success!fd=%d\n",fd);
int n_write=write(fd,buf,strlen(buf));
read(fd,readBuf,n_write);
printf("readBuf=%s\n",readBuf);
close(fd);
return 0;
}
发现啥都输出不了:
CLC@Embed_Learn:~/Linux_review/File_programming$ ./a.out
open success!fd=3
readBuf=
原来是光标的问题,write完了以后文件光标就在EOF了,所以我们有两种解决方案:
2.4.1 重新打开文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* buf="William is handsome";
char* readBuf;
readBuf=(char*)malloc(sizeof(buf));
int fd;
fd=open("./TestFile2",O_RDWR|O_CREAT,0600);
int n_write=write(fd,buf,strlen(buf));
close(fd);
fd=open("./TestFile2",O_RDWR|O_CREAT,0600);
read(fd,readBuf,n_write);
printf("readBuf=%s\n",readBuf);
close(fd);
return 0;
}
可以执行了:
CLC@Embed_Learn:~/Linux_review/File_programming$ ./a.out
open success!fd=3
readBuf=William is handsome
2.4.2 光标移动 lseek
光标移动需要lseek函数:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
其中:
- fd 是文件描述符
- offset是偏移量
- whence主要有以下几种宏:
SEEK_SET 文件开头
SEEK_CUR 当前光标位置
SEEK_END 文件结尾
返回值:成功返回offset 失败返回-1
解决上述问题:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* buf="William is handsome";
char* readBuf;
readBuf=(char*)malloc(sizeof(buf));
int fd;
fd=open("./TestFile2",O_RDWR|O_CREAT,0600);
printf("open success!fd=%d\n",fd);
int n_write=write(fd,buf,strlen(buf));
lseek(fd,0,SEEK_SET);
read(fd,readBuf,n_write);
printf("readBuf=%s\n",readBuf);
close(fd);
}
也能成功:
CLC@Embed_Learn:~/Linux_review/File_programming$ ./a.out
open success!fd=3
readBuf=William is handsome
2.4.3 小妙招:计算文件大小
利用lseek函数可以计算文件大小:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int fd=open("./TestFile2",O_RDWR|O_CREAT,0600);
printf("open success!fd=%d\n",fd);
int size=lseek(fd,0,SEEK_END);
printf("size of file is=%d\n",size);
close(fd);
return 0;
}
CLC@Embed_Learn:~/Linux_review/File_programming$ ./a.out
open success!fd=3
size of file is=20
CLC@Embed_Learn:~/Linux_review/File_programming$ ls -l
-rw------- 1 CLC book 20 Sep 15 23:51 TestFile2
3.文件的操作
3.1 文件的一些补充概念
3.1.1 系统默认文件描述符
fd=0 :标准输入
fd=1 :标准输出
fd=2 :标准错误
3.1.2 静态文件与动态文件
静态文件:在磁盘里存着的文件
动态文件:被打开的文件
3.1.3 为什么要close?
在文件被打开后,是动态的,进行修改之后,需要使用close进行写入
3.2 小项目 自制cp命令
3.2.1 主函数的一些补充
为了在shell中可以对程序进行传参,这里引入main函数的完整写法:
#include <stdio.h>
int main(int argc,char** argv)
{
}
其中:
- argc: 传参的数量
- argv: 传的参数
3.2.2 自制cp代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc,char** argv)
{
if(argc!=3)
{
printf("error!");
exit(-1);
}
int fd=open(argv[1],O_RDWR|O_CREAT,0600);
int size=lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
char* buf;
buf=(char*)malloc(sizeof(char)*size+8);
read(fd,buf,size);
int fd2=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
write(fd2,buf,size);
close(fd);
close(fd2);
return 0;
}
尝试在shell下运行:
CLC@Embed_Learn:~/Linux_review/File_programming$ ./mycp demo1.c mycptest.c
查看一下结果:
CLC@Embed_Learn:~/Linux_review/File_programming$ vimdiff demo1.c mycptest.c
- #include <sys/types.h> |- #include <sys/types.h>
| #include <sys/stat.h> || #include <sys/stat.h>
| #include <fcntl.h> || #include <fcntl.h>
| #include <stdio.h> || #include <stdio.h>
| int main() || int ma