用到的文件I/O函数有以下几个:打开文件、读文件、写文件、关闭文件等
对应用到的函数有:open、read、write、close、lseek(文件指针偏移)
文件描述符:对于内核而言,所有打开的文件都通过文件按描述符引用。文件描述符是一个非负整数。当打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。当读、写一个文件时,使用open/creat返回的文件描述符标识该文件,将其作为参数传送给read或write。
linux系统下文件描述符0是标准输入,1是标准输出,2是标准出错,所以一般打开文件的时候文件描述符都是从3开始。
1. open函数
(1)头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
(2)函数原型
int open(const char *pathname, int flags);
a、pathname:打开或者创建的文件名字,如"text"
b、 flags:
O_RDONLY:只读打开
O_WRONLY:只写打开
O_RDWR:读、写打开
O_CREAT:若此文件不存在则创建它,使用O_CREAT时后面要跟文件的访问权限位,如O_CREAT,0777
O_APPEND:每次写时都追加到文件的尾端
O_EXCL :如果同时指定了O_CREAT,而文件已经存在,则出错,用此可以测试一个文件是否存在,如果不存在,则创建此文件,这使测试和创建两者成为一个原子操作
O_DSYNC:使每次write等待物理I/O操作完成,但是如果该写操作并不影响读取刚写入的数据,则不需等待文件属性被更新
O_NONBLOCK :如果path引用的是一个FIFO、一个块特殊文件或一个字符特殊文件,则此选项为文件的本次打开操作和后续的I/O操作设置非阻塞方式
O_NOCTTY:如果path引用的是 终端设备,则将该设备分配为此进程的控制终端
O_SYNC:使每次write要等待物理I/O操作完成,包括有该write引起的文件属性更新所需的I/O
O_TRUNC:如果文件存在,并且是常规文件而且以读写或者只写打开,则将其长度截断为0,如果文件是FIFO或终端设备文件,O_TRUNC标志被忽略,否则O_TRUNC不明确
O_DIRECTORY:如果pathname引用的不是目录,则出错
(3)返回值:
成功:文件描述符
失败:-1
2.read()函数
(1)头文件
#include <unistd.h>
(2)函数原型
ssize_t read(int fd, void *buf, size_t count);
参数:
a、fd:调用open后返回的文件描述符
b、buf:用来存放从文件中读到的数据的缓冲区
c、count:读取的字节数
(3)返回值
成功:读到的字节数,如果读到文件尾端,则返回0
失败:-1
3.write()函数
(1)头文件
#include <unistd.h>
(2)函数原型
ssize_t write(int fd, const void *buf, size_t count);
参数:
a、fd:调用open后返回的文件描述符
b、buf:从来存放数据的缓冲区
c、count:写入数据的字节数
(3)返回值:
成功:返回已写的字节数
失败:-1
4.close()函数
(1)头文件
#include <unistd.h>
(2)函数原型
int close(int fd);
参数:
a、fd:调用open后返回的文件描述符
5.lseek()函数
(1)头文件
#include <sys/types.h>
#include <unistd.h>
(2)函数原型
off_t lseek(int fd, off_t offset, int whence);
参数:
a、fd:调用open后返回的文件描述符
b、offset 和参数whence有关,通常设置为0 (according to thedirective whence as follows)
c、whence:
SEEK_SET: 将文件的偏移量设置为距文件开始处offset个字节
SEEK_CUR:将文件的偏移量设置为其当前值加offset个字节,offset可为正或负
SEEK_END: 将文件的偏移量设置为文件长度加offset,offset可为正或负
(3)返回值:
成功:返回新的文件偏移量
失败:-1
实际操作
代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main(){
int tempFd = 0;
char tempFileName[20] = "test.txt";
//Step 1. open the file.
tempFd = open(tempFileName, O_RDWR|O_EXCL|O_TRUNC, S_IRWXG);
if(tempFd == -1){
perror("file open error.\n");
exit(-1);
}//of if
//Step 2. write the data.
int tempLen = 0;
char tempBuf[100] = {0};
scanf("%s", tempBuf);
tempLen = strlen(tempBuf);
write(tempFd, tempBuf, tempLen);
close(tempFd);
//Step 3. read the file
tempFd = open(tempFileName, O_RDONLY);
if(tempFd == -1){
perror("file open error.\n");
exit(-1);
}//of if
off_t tempFileSize = 0;
tempFileSize = lseek(tempFd, 0, SEEK_END);
lseek(tempFd, 0, SEEK_SET);
while(lseek(tempFd, 0, SEEK_CUT)!= tempFileSize){
read(tempFd, tempBuf, 1024);
printf("%s\n", tempBuf);
}//of while
close(tempFd);
return 0;
}//of main
运行截图
将写好的代码保存好之后,使用gcc来进行预编译等操作
总结
通过本次学习,我学到了c语言对于文件操作的几种常用方法,也熟悉了Linux环境下的程序编写流程,同时通过观察老师的代码我也理解了编写过程中格式规范的重要性,只有拥有完备注释与格式的代码才可以进行正常的维护调试,在今后的学习工作中我将瑾记今天学到的内容,通过不断的积累提升自己。