打开 /创建文件
man 2 open
open的系统调用
系统调用open的作用是打开一个文件,并返回这个文件的描述符。
简单地说,open建立了一条到文件或设备的访问路径。如果操作成功,它将返回一个文件描述符,read和write等系统调用使用该文件描述符对文件或
设备进行操作。这个文件描述符是唯一的,他不会和任何其他运行中的进程共享。如果两个程序同时打开一个文件,会得到两个不同的问价描述符。如果
同时对两个文件进行操作,他们各自操作,互补影响,彼此相互覆盖(后写入的覆盖先写入的)为了防止文件按读写冲突,可以使用文件锁的功能。
Linux中open的函数原型有两个:
int open(const char *path, int oflags);
int open(const char *path, int flags, mode_t mode );
参数说明。
path:准备打开的文件或设备名字。
flags:指出要打开文件的访问模式。
open调用必须指定如下所示的文件访问模式之一:
open调用哈可以在flags参数中包括下列可选模式的组合(用”按位或“操作):
- O_APPEND: 每次把写入数据追加在文件的末尾。
- O_TRUNC: 属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截断为0.
- O_CREAT: 如果需要,就按参数mode中给出的访问模式创建文件。
- O_EXCL: 与O_CREAT一起调用,确保调用者创建出文件。使用这个模式可防止两个程序同时创建一个文件,如果文件已经存在,open调用将失败。
关于其他可能出现的flags值,请看考open的调用手册。
mode:当使用O_CREAT标志的open来创建文件时,我们必须使用三个参数格式的open调用。第三个参数mode 是几个标志按位OR后得到的。他们是:
- S_IRUSR: 读权限,文件属主。
- S_IWUSR:写权限,文件属主。
- S_ IXUSR:执行权限,文件属主。
- S_IRGRP:读权限,文件所属组。
- S_IWGRP:写权限,文件所属组。
opentest2.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd = open("./file1",O_RDWR);
if(fd == -1)
{
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0)
{
printf("create file1 success\n");
}
}
printf("fd = %d\n",fd);
return 0;
}
-rw-r--r-- 1.可读 r 4 int open(const char *path, int flags, mode_t mode );
2.可写 w 2 fd = open("./file1",O_RDWR|O_CREAT,0600);
3.执行 x 1 0600 6指4+2 可读可写 而后面的 0 0 分别为 同组 和其他组
opennew7.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd = open("./file1",O_RDWR|O_CREAT|O_EXCL,0600);
if(fd == -1){
printf("file exit\n");
}
return 0;
}
主要是针对 添加 O_EXCL 的使用,O_EXCL: 与O_CREAT一起调用,确保调用者创建出文件。使用这个模式可防止两个程序同时创建一个文件,如果文件已经存在,open调用将失败。
O_APPENDtest8.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "ganboss is very handsome!";
fd = open("./file1",O_RDWR|O_APPEND);
printf("open success : fd = %d\n",fd);
// ssize_t write(int fd, const void *buf, size_t count);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write %d byte to file\n",n_write);
}
// int close(int fd);
close(fd);
return 0;
}
O_APPEND: 每次把写入数据追加在文件的末尾。 意思就是在原有的内容file1 (132123132123123132) 增加内容你要的内容(ganboss is very handsome)
O_TRUNCtest9.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "test!";
fd = open("./file1",O_RDWR|O_TRUNC);
printf("open success : fd = %d\n",fd);
// ssize_t write(int fd, const void *buf, size_t count);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write %d byte to file\n",n_write);
}
// int close(int fd);
close(fd);
return 0;
}
O_TRUNC: 属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截断为0. 全部内容清理掉 变成 test!
文件写入操作
man 2 write
write的系统调用
write,就是把缓冲区的数据写入文件中。注意,这里的文件时广泛意义的文件,比如写入磁盘、写入打印机等等。
Linux 中write()的函数原型:
size_t write(int fildes, const void *buf, size_t nbytes);
参数说明:
fildes:文件描述符,标识了要写入的目标文件。例如:fildes的值为1,就像标准输出写数据,也就是在显示屏上显示数据;如果为 2 ,则想标注错误写数据。
*buf:待写入的文件,是一个字符串指针。
nbytes:要写入的字符数。
函数返回值:size_t 返回成功写入文件的字符数。需要指出的是,write可能会报告说他写入的字节比你所要求的少。这并不一定是个错误。在程序中,你需要检查error已发现错误,然后再次调用write写入剩余的数据。
writetest3.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd;
char *buf = "ganboss is very handsome!";
fd = open("./file1",O_RDWR);
if(fd == -1)
{
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0)
{
printf("create file1 success\n");
}
}
printf("open success : fd = %d\n",fd);
// ssize_t write(int fd, const void *buf, size_t count);
write(fd,buf,strlen(buf));
// int close(int fd);
close(fd);
return 0;
}
// ssize_t write(int fd, const void *buf, size_t count);
char *buf = "ganboss is very handsome!";
用到了strlen去计算write要写入字符串的多少
所以要加头文件#include <string.h>
close系统调用
close系统调用用于“关闭”一个文件,close调用终止一个文件描述符fildes以其文件之间的关联。文件描述符被释放,并能够重新使用。
close成功返回1,出错返回-1.
#Include<unistd.h>
int close(int fildes);
read的系统调用
系统调用read是从文件中读出数据。要读取的文件用文件描述符标识,数据读入一个事先定义好的缓冲区。他返回实际读入的字节数。
Linux中read的函数原型:
size_t read(int fildes, void *buf, size_t nbytes);
参数说明:
fildes:文件描述符,标识要读取的文件。如果为0,则从标准输入读数据。类似于scanf()的功能。
*buf:缓冲区,用来存储读入的数据。
nbytes:要读取的字符数。
返回值:size_t返回成功读取的字符数,它可能会小于请求的字节数。
readtest4.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "ganboss is very handsome!";
fd = open("./file1",O_RDWR);
if(fd == -1)
{
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0)
{
printf("create file1 success\n");
}
}
printf("open success : fd = %d\n",fd);
// ssize_t write(int fd, const void *buf, size_t count);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write %d byte to file\n",n_write);
}
close(fd);
fd = open("./file1",O_RDWR);
char *readBuf;
readBuf = (char *)malloc(sizeof(char)*n_write + 1);//强制转换指针 malloc
// ssize_t read(int fd, void *buf, size_t count);
int n_read = read(fd,readBuf,n_write);
printf("read : %d,contex : %s\n",n_read,readBuf);
// int close(int fd);
close(fd);
return 0;
运行结果为:
重新打开的方法: 这个是打开open 文件夹 再写入write 字符串 然后关闭close文件夹 再打开open 让光标跑到前面去读取read前面的内容 若不这样可能光标在字符串后面 什么也读不到 可以通过对光标的闪烁位置进行改动
文件光标的移动操作
解决上面方法是:去重新定位光标
将文件读写指针相对whence移动offset个字节 (offset对whence的偏移值)
off_t lseek(int fd, off_t offset, int whence);
所需要头文件:
#include <sys/types.h>
#include <unistd.h>
参数:
fd 表示要操作的文件描述符
offset是相对于whence(基准)的偏移量
whence 可以是SEEK_SET(文件指针开始),SEEK_CUR(文件指针当前位置) ,SEEK_END为文件指针尾
返回值:文件读写指针距文件开头的字节大小,出错,返回-1
lseek 主要作用是移动文件读写指针,因此还有以下两个作用
1.拓展文件,不过一定要一次写的操作。迅雷等下载工具在下载文件时候先扩展一个空间,然后再下载的。
2.获取文件大小
lseektest5.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "ganboss is very handsome!";
fd = open("./file1",O_RDWR);
if(fd == -1)
{
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0)
{
printf("create file1 success\n");
}
}
printf("open success : fd = %d\n",fd);
// ssize_t write(int fd, const void *buf, size_t count);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write %d byte to file\n",n_write);
}
// close(fd);
// fd = open("./file1",O_RDWR);
// off_t lseek(int fd, off_t offset, int whence);
char *readBuf;
readBuf = (char *)malloc(sizeof(char)*n_write + 1);//qiangzhi zhizhen
// ssize_t read(int fd, void *buf, size_t count);
// lseek(fd,0,SEEK_SET);
lseek(fd,-25,SEEK_CUR);
int n_read = read(fd,readBuf, n_write);
printf("read : %d,contex : %s\n",n_read,readBuf);
// int close(int fd);
close(fd);
return 0;
}
运行结果为:
lseeknew6.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "ganboss is very handsome!";
fd = open("./file1",O_RDWR);
int filesize = lseek(fd,0,SEEK_END);
printf("file's size is %d\n",filesize);
close(fd);
return 0;
}
运行结果为:
creat的系统调用
int creat(const char *filename, mode_t mode)
filename:要创建的文件名(包含路径,缺省为当前路径)
mode:创建模式
creat的返回值为文件描述符,其本质为一个非负整数,是由系统分配。文件说明符的范围为0 - OPEN_MAX。早期的UNIX版本OPEN_MAX = 19,即允许每个进程同时打开20个文件,现在很多系统则将其增加到1024.
常见的创建模式:
S_IRUSR 可读 4 (可以用数字来表示访问权限)
S_IWUSR 可写 2 (无任何权限->0)
S_IXUSR 可执行 1
S_IRWXU 可读、可写、可执行 7
createtest10.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "test!";
// int creat(const char *pathname, mode_t mode);
fd = creat("/home/ganboss/syslinux/11fileop/file1",S_IRWXU);
return 0;
}
运行结果为: 让 a.out 变成 -rwxr-xr-x