1.Linux系统IO函数
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int close(int fd);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
off_t lseek(int fd, off_t offset, int whence);
1.1 open函数(仅打开文件)
通过命令man 2 open
可以看到函数功能描述,包含函数参数、参数说明等。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
使用open函数需要包含以上的头文件,其中函数的声明在fcntl.h文件,前两个文件包含的是flags的宏定义。
int open(const char *pathname, int flags);
pathname是文件名的字符串数组,flags必须包含以下的访问模式标志位之一:O_RDONLY, O_WRONLY, O_RDWR。这三个标志位的宏定义就在前两个头文件里面,分别代表只读、只写、读写。这三个标志位是互斥的,只能三选一。
open函数会返回一个文件描述符,一个较小的、非负数整数,用于定位到该文件。如果打开文件存在错误,就会返回-1。
1.2 perror函数的使用
通过man 3 perror
可以打开perror函数的说明,这个错误用于打印系统最近的错误信息。因为前面的open只能返回-1,而不知道具体的错误。Linux系统函数库中存在一个全局变量errno,记录了最近一次的错误号,每个错误号代表了具体错误信息。
#include <stdio.h>
void perror(const char *s);
使用该函数需要加入头文件stdio.h,函数的参数s代表自定义的用户名。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main() {
int fd = open("abc.txt", O_RDONLY);
if (fd == -1)
perror("openError");
return 0;
}
一个简单的main函数,并且通过gcc编译成可执行文件。
可以看到终端输出了具体的调试信息,显示并没有这样的文件。
1.3 open函数(可创建文件)
int open(const char *pathname, int flags, mode_t mode);
pathname:代表要创建的文件路径
flags:
1.必选项:O_RDONLY、O_WRONLY、 O_RDWR,三选一;
2.可选项:O_CREAT 如果文件不存在,创建新文件
mode:八进制的数,表示用户对创建出的新文件的操作权限。当flags参数中存在O_CREAT或O_TMPFILE时,必须提供该参数。如果没有上述两个标志位,可以忽略该参数。具体的参数由宏定义提供,包括读权限、写权限、执行权限等,对使用者也区分为用户、组、其他。
int fd = open("create.txt", O_RDWR | O_CREAT, S_IRWXU);
通过上述代码可以完成一个新文件的创建,并且规定用户具备读、写、执行的权限。flags是按位或,同时取两个标志位。
1.4 read函数和write函数
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
函数说明:
read函数试图从文件描述符fd所指定的文件读取内容到buf所指定的内存当中。在支持读取的文件中,读操作从当前文件偏移开始,随着读取字节的增加,文件偏移也会增加。如果文件偏移达到了文件末尾,无字节可读,read函数会返回0 。
参数说明:
fd:通过open函数返回的文件描述符;
buf:读出数据存放的地方
count:指定数组的大小
返回值:
如果读取成功,会返回读到内容的字节大小。如果出现错误,函数返回-1,并且会将errno这个全局变量设置成合适的值。
#include <unistd.h>
ssize_t write(int fd,const void *buf, size_t count);
wirte函数和read函数类似。
返回值:
如果写入成功,会返回写入文件的字节大小。如果出现错误,函数返回-1,并且会将errno这个全局变量设置成合适的值。
下面运用read函数和write函数,完成文件的复制。
//abc.txt
abcdefghijkl
//copy.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(){
//打开文件
int srcfd = open("abc.txt", O_RDONLY);
//创建新文件
int destfd = open("cpy.txt", O_WRONLY | O_CREAT, S_IRWXU);
//读写操作
char buf[1024] = {0};
int len = 0;
while((len = read(srcfd, buf, sizeof(buf))) > 0){
write(destfd, buf, len);
printf("%d\n", len);
}
//关闭文件
close(srcfd);
close(destfd);
return 0;
}
对copy.c进行编译得到可执行文件copy,执行copy,在终端输出了13,代表读取了13个字符并写入新的文件。
通过ls
命令显示存在文件,可以看到出现了新的cpy.txt文件,打开文件,内容和abc.txt一致,说明复制成功。
1.5 lseek函数
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
函数说明:
该功能重新配置已打开文件的偏移。
参数说明:
fd:文件描述符;
offset:偏移量
whence:标志位
1.SEEK_SET:设置文件指针的偏移量
2.SEEK_CUR:设置文件指针=当前位置+第二个参数偏移量offset
3.SEEK_END:设置文件指针=文件大小+第二个参数偏移量offset
返回值:
如果设置成功,函数返回当前文件指针相对于文件头的偏移。如果失败,返回-1,并且设置errno全局变量。
举例:
lseek(fd, 0, SEEK_SET); //移动文件指针到文件头
lseek(fd, 0, SEEK_CUR); //获得当前文件指针
lseek(fd, 0, SEEK_END); //获得文件长度
lseek(fd, 100, SEEK_END); //从文件末尾拓展文件长度
1.6 stat函数、lstat函数
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);
函数说明:
stat函数用于获取一个文件相关的信息。
参数:
pathname:文件路径字符串
buf:一个存放返回信息的结构体指针
返回值:如果成功返回0,失败则返回-1,同时全局变量errno被设置为相应的值。
lstat函数针对符号链接,lstat 返回链接本身信息,而不是而非目标文件。
//stat结构体的内容
struct stat {
dev_t st_dev; //文件的设备编号
ino_t st_ino; //节点
mode_t st_mode; //文件类型和存取的权限
nlink_t st_nlink; //连到该文件的硬连接数目
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //设备文件的设备编号
off_t st_size; //文件字节数
blksize_t st_blksize; //块大小
blkcnt_t st_blocks; //块数
struct timespec st_atim; //最后一次访问时间
struct timespec st_mtim; //最后一次修改时间
struct timespec st_ctim; //最后一次改变时间(指属性)
};
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(){
struct stat statbuf;
int ret = stat("abc.txt", &statbuf);
if (ret == -1) {
perror("stat");
return -1;
}
printf("size:%ld\n", statbuf.st_size);
return 0;
}
编译并执行main,可以看到终端输出对应信息。