大多数文件I/O用到的函数:open(), close(), lseek(), read(), write()
这些都是不带缓冲的I/O,不带缓冲的意思是直接进行是内核的一个系统调用,并且ISO C库里面不含有这些标准。他们是POSIX.1和Single Unix Specification的组成部分。
内核采用文件描述符来表示和引用文件,所以上面的函数都是对文件描述符进行操作的。
open()函数有两个版本,第一个参数是路经名,第二个参数是打开的模式,只读,只写,可读,可写等。
如果创建文件的话要指定第三个参数,说明文件的掩码。
close()函数关闭指定的文件描述符,因为当一个进程终止的时候会自动关闭所有它打开的文件,所以一般不显示关闭文件。
lssek()函数,更改当前文件的偏移量,其中第三个参数有SEEK_SET,SEEK_CUR,SEEK_END,分别是开始,当前和结尾。
read()函数,从相对应的文件描述符中读取一定字节的数据,返回值为读取的字节数,如果读取的字节数为0的话说明到达了文件尾部。如果是-1,则表示出错。
write()函数,向相应的文件描述符中写数据。返回值和写的值相同。不相同的话则表示出错。
下面是自己用这几个函数写的一个复制文件的程序:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define MAX_NUMBER 4096
#define CREATE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
char buf[MAX_NUMBER];
void sys_error(const char *message) {
printf("%s\n", message);
exit(0);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
sys_error("correct usage: copy file1 file2");
}
int source_fd, destination_fd;
if ((source_fd = open(argv[1], O_RDONLY)) == -1) {
sys_error("can not open file1");
}
if ((destination_fd = open(argv[2], O_WRONLY | O_CREAT | O_EXCL, CREATE_MODE)) == -1) {
char flag[MAX_NUMBER];
printf("the name of file2 exist, do you want to overwrite it?y/n\n");
scanf("%s", flag);
while (strcmp(flag, "y") != 0 && strcmp(flag, "n") != 0) {
printf("y/n\n");
scanf("%s", flag);
}
if (strcmp(flag, "n") == 0) {
sys_error("file2 exist");
}
else {
if ((destination_fd = open(argv[2], O_WRONLY)) == -1) {
sys_error("can not open file2");
}
}
}
int read_byte;
while ((read_byte = read(source_fd, buf, MAX_NUMBER)) > 0) {
/* printf("%d:%s\n", read_byte, buf); */
if (write(destination_fd, buf, read_byte) != read_byte) {
if (errno == EBADF) {
printf("bad fd\n");
}
sys_error("write error");
}
}
printf("copy finished\n");
return 0;
}