本文介绍Linux下的文件操作的系统调用方法,是我自学Linux编程的学习笔记。
1. 文件描述符
任何打开的文件都将被分配一个唯一标识该打开文件的文件描述符,为一个大于等于0的整数。
系统启动后默认打开的文件流有标准输入设备(stdin),标准输出设备(stdout)和标准错误输出设备
(stderr),其文件描述符分别为0,1,2。以后打开的文件描述符分配依次增加,使用fileno()函数
可以返回一个流对应的文件描述符。
函数和常量定义说明:
在Linux输入命令man fileno,man给出的内容显示fileno是一个ANSI C的标准函数,定义在
<stdio.h>中,在FC6下通过试验得知,stdin,stdout,stderr三个常量必须用小写才能编译通过。
文件描述符定义如:int fd;
打印文件描述符的例子:
执行结果:
stdin is:0
stdout is:1
stderr is:2
2. 打开文件
对文件操作之前需要先打开文件,获得该文件的文件描述符,打开文件的系统调用为open函数。
该函数定义头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数原型:int open(const char *pathname, int flag);
int open(const char *pathname, int flag, mode_t mode);
参数说明:
pathname:要打开文件的文件名指针,即一个字串,如"/home/zcc/test.txt"
flag :打开文件的方式,使用man open发现一共有十几种打开方式,但是我们平时使用的只有几种
mode :如果要打开的文件不存在,open会创建文件,即使用O_CREAT打开文件,此时要用第三个参数
它规定了文件的权限,在设置权限时,可采用直接设置为八进制的方式,如0666,也可以使用
文件权限宏定义。只有第二个参数含有O_CREAT时这个参数才有用。
返回值 :成功后返回打开文件的文件描述符(int型),失败返回-1。
O_RDONLY:只读方式打开文件
O_WRONLY:只写方式打开文件
O_RDWR :读写方式打开文件
O_CREAT :若要打开的文件不存在,则自动建立该文件
O_EXCL :当和O_CREAT一起使用的时候,如果文件已经存在,那么会出错;如果文件不存在则建立文件
如果要打开的文件为符号连接,则打开文件出错。O_EXCL不能打开NFS系统格式的文件。
O_SYNC :以I/O同步方式打开文件,如果打开文件的同时有其他进程对该文件进行写操作,则此次打开
文件调用将被阻塞知道其他进程将数据写如物理介质(如磁盘)。
O_APPEND:当读写文件时从文件尾开始移动,即写文件时以追加的方式。
open的man页说当使用open的时候flag参数必须包含O_RDONLY,O_WRONLY,O_RDWR中的一种,我感觉不是这样啊?!
创建文件时权限设置,文件权限宏可以通过man open来查看
3. 关闭文件
完成对文件的操作一定要关闭文件以便将内容写入到文件中。使用close函数来关闭文件
该函数定义的头文件: #include <unistd.h>
函数原型: int close(int fd);
参数说明:只有一个参数,即调用open函数打开文件时返回的文件描述符。
返回值 :成功返回0,失败返回-1并设置errno标志位。
4. 创建文件
除了使用open创建文件外,还可以使用creat创建。
头文件定义:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数原型:int creat(const char *pathname, mode_t mode);
参数说明:
pathname:要创建的文件的路径和文件名,如"./home/root/tmp"
mode: 文件的权限描述
返回值 :成功返回创建的文件的文件描述符,失败返回-1,并把错误代码设置为error
open,close,creat函数的例子:
5. 读文件内容
使用read方法从一个文件中读取数据。
头文件定义:
#include <unistd.h>
函数原型:ssize_t read(int fd, void *buf, size_t count);
参数说明:
fd:要读取的文件的文件描述符
buf:存放读取的内容
count:读取的字数,如果为0则read()不起作用并返回0
返回值 :返回值类型为ssize_t,即int型,返回值为读取的字数,如果返回0表示已经达到文件尾部
或无数据可读,文件的读写位置会随读取到的字节移动。
6. 写内容到文件
打开文件后使用write方法向文件写入数据。
头文件定义: #include <unistd.h>
函数原型: ssize_t write(int fd, const void *buf, size_t count);
参数说明:和read基本一样。
返回值:返回值为写入的字数。
注意:这个函数是不带缓冲的。ANSI C的写函数带缓冲功能。
读写文件内容例子:
7. POSIX标准提供的其他方法
POSIX不仅提供了基本的文件操作方法,还提供了更高级的用法,比如文件控制,锁定/解锁定,文件定位。
不过这些方法对一般的应用都不不常用的,这里只列出方法名,不做详细介绍。这部分我也没有系统学习,由于
不常用,用到了查手册。
fcntl 对打开的文件进行控制
lockf 锁定文件
flock 锁定解锁定文件
lseek 文件定位
lseek定义在:#include <sys/types.h> #include <unistd.h>
函数原型:off_t lseek(int fildes, off_t offset, int whence);
参数说明:fildes:文件描述符
offset:根据参考位置(第三个参数)来移动读写位置的位移数
whence:设置的读写参考位置,取值为:
SEEK_SET 0 //文件起始位置
SEEK_CUR 1 //当前位置
SEEK_END 2 //文件结束位置
返回值: 执行成功返回目前读写位置,即举例文件头部的字节数,错误返回-1
例子:
1. 文件描述符
任何打开的文件都将被分配一个唯一标识该打开文件的文件描述符,为一个大于等于0的整数。
系统启动后默认打开的文件流有标准输入设备(stdin),标准输出设备(stdout)和标准错误输出设备
(stderr),其文件描述符分别为0,1,2。以后打开的文件描述符分配依次增加,使用fileno()函数
可以返回一个流对应的文件描述符。
函数和常量定义说明:
在Linux输入命令man fileno,man给出的内容显示fileno是一个ANSI C的标准函数,定义在
<stdio.h>中,在FC6下通过试验得知,stdin,stdout,stderr三个常量必须用小写才能编译通过。
文件描述符定义如:int fd;
打印文件描述符的例子:
- #include <stdio.h>
- int main()
- {
- printf("stdin is:%d/n", fileno(stdin));
- printf("stdout is:%d/n", fileno(stdout));
- printf("stderr is:%d/n", fileno(stderr));
- return 0;
- }
执行结果:
stdin is:0
stdout is:1
stderr is:2
2. 打开文件
对文件操作之前需要先打开文件,获得该文件的文件描述符,打开文件的系统调用为open函数。
该函数定义头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数原型:int open(const char *pathname, int flag);
int open(const char *pathname, int flag, mode_t mode);
参数说明:
pathname:要打开文件的文件名指针,即一个字串,如"/home/zcc/test.txt"
flag :打开文件的方式,使用man open发现一共有十几种打开方式,但是我们平时使用的只有几种
mode :如果要打开的文件不存在,open会创建文件,即使用O_CREAT打开文件,此时要用第三个参数
它规定了文件的权限,在设置权限时,可采用直接设置为八进制的方式,如0666,也可以使用
文件权限宏定义。只有第二个参数含有O_CREAT时这个参数才有用。
返回值 :成功后返回打开文件的文件描述符(int型),失败返回-1。
O_RDONLY:只读方式打开文件
O_WRONLY:只写方式打开文件
O_RDWR :读写方式打开文件
O_CREAT :若要打开的文件不存在,则自动建立该文件
O_EXCL :当和O_CREAT一起使用的时候,如果文件已经存在,那么会出错;如果文件不存在则建立文件
如果要打开的文件为符号连接,则打开文件出错。O_EXCL不能打开NFS系统格式的文件。
O_SYNC :以I/O同步方式打开文件,如果打开文件的同时有其他进程对该文件进行写操作,则此次打开
文件调用将被阻塞知道其他进程将数据写如物理介质(如磁盘)。
O_APPEND:当读写文件时从文件尾开始移动,即写文件时以追加的方式。
open的man页说当使用open的时候flag参数必须包含O_RDONLY,O_WRONLY,O_RDWR中的一种,我感觉不是这样啊?!
创建文件时权限设置,文件权限宏可以通过man open来查看
3. 关闭文件
完成对文件的操作一定要关闭文件以便将内容写入到文件中。使用close函数来关闭文件
该函数定义的头文件: #include <unistd.h>
函数原型: int close(int fd);
参数说明:只有一个参数,即调用open函数打开文件时返回的文件描述符。
返回值 :成功返回0,失败返回-1并设置errno标志位。
4. 创建文件
除了使用open创建文件外,还可以使用creat创建。
头文件定义:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数原型:int creat(const char *pathname, mode_t mode);
参数说明:
pathname:要创建的文件的路径和文件名,如"./home/root/tmp"
mode: 文件的权限描述
返回值 :成功返回创建的文件的文件描述符,失败返回-1,并把错误代码设置为error
open,close,creat函数的例子:
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdio.h>
- int main(int argc, char *argv[])
- {
- //声明三个文件描述符,分别代表打开,打开创建,创建的文件描述符
- int fd_open, fd_open_create, fd_create;
- //open exit file
- if(-1 == (fd_open = open("/bin/ls", O_RDONLY)))
- {
- printf("open file error");
- }
- else
- {
- printf("the file's descriptor is %d/n", fd_open);
- }
- //open file, if it is not exit, create it
- if(-1 == (fd_open_create = open("./tmp", O_CREAT | O_EXCL, 0644)))
- {
- printf("open create file error");
- }
- else
- {
- printf("the tmp descriptor is %d/n", fd_open_create);
- }
- //create file
- if(-1 == (fd_create = creat("./tmp2", 0644)))
- {
- printf("create file error");
- }
- else
- {
- printf("the tmp2 file descriptor is %d/n", fd_create);
- }
- //close files
- close(fd_open);
- close(fd_create);
- close(fd_open_create);
- return 0;
- }
使用read方法从一个文件中读取数据。
头文件定义:
#include <unistd.h>
函数原型:ssize_t read(int fd, void *buf, size_t count);
参数说明:
fd:要读取的文件的文件描述符
buf:存放读取的内容
count:读取的字数,如果为0则read()不起作用并返回0
返回值 :返回值类型为ssize_t,即int型,返回值为读取的字数,如果返回0表示已经达到文件尾部
或无数据可读,文件的读写位置会随读取到的字节移动。
6. 写内容到文件
打开文件后使用write方法向文件写入数据。
头文件定义: #include <unistd.h>
函数原型: ssize_t write(int fd, const void *buf, size_t count);
参数说明:和read基本一样。
返回值:返回值为写入的字数。
注意:这个函数是不带缓冲的。ANSI C的写函数带缓冲功能。
读写文件内容例子:
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- int main(int argc, char *argv[])
- {
- char str[] = "I am Chinese!/n";
- int fd = open("./tmp", O_RDWR);
- if(-1 == fd)
- {
- printf("opean file error/n");
- return 0;
- }
- if(sizeof(str) != (write(fd, str, sizeof(str))
- {
- printf("write file error/n");
- return 0;
- }
- close(fd);//这里关闭不关闭都可以,最后一定要关闭。
- char buf[30];
- open("./tmp", O_RDONLY);
- ssize_t size = read(fd, buf, sizeof(buf));
- close(fd);
- printf("read %d from file, they are %s/n", size, buf);
- }
7. POSIX标准提供的其他方法
POSIX不仅提供了基本的文件操作方法,还提供了更高级的用法,比如文件控制,锁定/解锁定,文件定位。
不过这些方法对一般的应用都不不常用的,这里只列出方法名,不做详细介绍。这部分我也没有系统学习,由于
不常用,用到了查手册。
fcntl 对打开的文件进行控制
lockf 锁定文件
flock 锁定解锁定文件
lseek 文件定位
lseek定义在:#include <sys/types.h> #include <unistd.h>
函数原型:off_t lseek(int fildes, off_t offset, int whence);
参数说明:fildes:文件描述符
offset:根据参考位置(第三个参数)来移动读写位置的位移数
whence:设置的读写参考位置,取值为:
SEEK_SET 0 //文件起始位置
SEEK_CUR 1 //当前位置
SEEK_END 2 //文件结束位置
返回值: 执行成功返回目前读写位置,即举例文件头部的字节数,错误返回-1
例子:
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- int main()
- {
- int fd = open("./lseek.c", O_RDONLY);
- lseek(fd, 30, SEEK_SET);
- char s[100];
- read(fd, s, sizeof(s));
- close(fd);
- printf("%s", s);
- }