Linux文件IO
1.文件IO分类
linux操作文件有两套:系统调用IO和标准IO
**系统调用IO:**open/read/write/lseek/fsync/close
**标准IO:**fopen/fread/fwrite/fseek/fflush/fclose
两种区别在于:
标准 IO 的内部,会分配一个用户空间的 buffer,读写操作先经过这个 buffer。在有必
要时,才会调用底下的系统调用 IO 向内核发起操作。
所以:标准 IO 效率更高;但是要访问驱动程序时就不能使用标准 IO,而是使用系统调
用 IO。
2.打开文件
open 函数描述
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
//函数功能及用法
// ./open 1.txt
// argv[0]= "open"
// argv[1]="1.txt"
//int argc: 这是命令行参数的数量。包括程序名本身和所有传递给程序的参数。例如,在命令 ./open 1.txt 中,argc 的值是 2。
//char **argv: 这是一个字符串数组,包含了传递给程序的所有命令行参数。argv[0] 是程序的名称("open"),argv[1] 是第一个实际参数("1.txt")。argv 是一个指向字符串的指针数组。
int main(int argc, char **argv)
{
int fd;//句柄
if (argc != 2)
{
printf("usage :%s <file>\n", argv[0]);
}
fd = open(argv[1],O_RDWR) ;
if (fd<0)
{
printf("can not open %s\n",argv[1]);
printf("errno =%d\n",errno);
printf("err:%s\n",strerror(errno));
perror("open");
}
else
{
printf("fd=%d\n",fd);
}
while (1)
{
sleep(10);
}
close(fd);
return 0;
}
3.创建文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
// ./create 1.txt
// argv[0]= "open"
// argv[2]="1.txt"
int main(int argc, char **argv)
{
int fd;
if (argc != 2)
{
printf("usage :%s <file>\n", argv[0]);
}
fd = open(argv[1],O_RDWR | O_CREAT | O_TRUNC ,0777) ;
if (fd<0)
{
printf("can not open %s\n",argv[1]);
printf("errno =%d\n",errno);
printf("err:%s\n",strerror(errno));
perror("open");
}
else
{
printf("fd=%d\n",fd);
}
while (1)
{
sleep(10);
}
close(fd);
return 0;
}
创建文件是在打开文件基础之上进行对文件的权限进行操作
fd = open(argv[1],O_RDWR | O_CREAT | O_TRUNC ,0777) ;
注意:无法更改已有文件的权限
具体函数说明看open函数说明
文件权限相关知识:
(1) 权限=人+事物属性
(2)查看文件权限 ls -l
(3)**Linux的文件属性可以有:读、写、执行:r w x
(4)文件的身份三类别:文件拥有者(owner),所属组(group),其他人(others)
4.写文件
write函数原型
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
// ./write 1.txt str1 str2
// argc =2
// argv[0]= "open"
// argv[1]="1.txt"
int main(int argc, char **argv)
{
int fd;
int i;
int len;
if (argc <3 )
{
printf("usage :%s <file> <string1> <string2> ...\n", argv[0]);
return -1;
}
fd = open(argv[1],O_RDWR | O_CREAT | O_TRUNC ,0777) ;
if (fd<0)
{
printf("can not open %s\n",argv[1]);
printf("errno =%d\n",errno);
printf("err:%s\n",strerror(errno));
perror("open");
}
else
{
printf("fd=%d\n",fd);
}
for(i =2; i < argc;i++)
{
len = write(fd,argv[i],strlen(argv[i]));
if(len != strlen(argv[i]))
{
perror("write");
break;
}
write(fd,"\r\n",2);
}
close(fd);
return 0;
}
5.读文件
read函数描述
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
// ./read 1.txt
// argc =2
// argv[0]= "read"
// argv[1]="1.txt"
int main(int argc, char **argv)
{
int fd;
int i;
int len;
unsigned char buf[100];
if (argc != 2)
{
printf("usage :%s <file> <string1> <string2> ...\n", argv[0]);
}
fd = open(argv[1],O_RDONLY) ;
if (fd < 0)
{
printf("can not open %s\n",argv[1]);
printf("errno =%d\n",errno);
printf("err:%s\n",strerror(errno));
perror("open");
}
else
{
printf("fd=%d\n",fd);
}
// 读文件/打印
while(1)
{
len=read(fd,buf,sizeof(buf)-1);
if(len < 0)
{
perror("read");
close(fd);//这里不加这一行代码会怎么样???
return -1;
}
else if(len == 0)
{
break;
}
else
{
// buf[0]...buf[len-1] 含有读出的数据
// buf[len]='\0' 读出结束符
buf[len]='\0';
printf("%s",buf);
}
}
close(fd);
return 0;
}
(1)因为read函数是n个字节的数据放入buf中,所以需要预先创建一个unsigned char buf[100]字符数组来存入数据;
(2)read函数返回值为读取的实际读取的字节数(ssize_t
类型)
(3)在read(fd, buf, sizeof(buf) - 1)
的调用中,sizeof(buf) - 1
是为了留出一个字节的位置,以确保在读取数据后,buf
能够以空字符(\0
)结尾,从而安全地将数据作为C字符串处理。这是一种常见的做法,用于确保读取到的内容不会超出缓冲区的边界,并且可以安全地进行字符串操作。
dup
ead函数是n个字节的数据放入buf中,所以需要预先创建一个unsigned char buf[100]字符数组来存入数据;
(2)read函数返回值为读取的实际读取的字节数(ssize_t
类型)
(3)在read(fd, buf, sizeof(buf) - 1)
的调用中,sizeof(buf) - 1
是为了留出一个字节的位置,以确保在读取数据后,buf
能够以空字符(\0
)结尾,从而安全地将数据作为C字符串处理。这是一种常见的做法,用于确保读取到的内容不会超出缓冲区的边界,并且可以安全地进行字符串操作。