一、UNIX/Linux 的一个基本哲学是“一切皆文件”。Linux 文件按其代表的具体对象,可大致分类为:
-
普通文件,即一般意义上的文件、磁盘文件;
-
设备文件,代表的是系统中一个具体的设备;
-
管道文件、FIFO 文件,一种特殊文件,常用于进程间通信;
-
套接字(socket)文件,主要用在网络通信方面。
二、文件 I/O 的常用操作方法有“打开”、“关闭”、“读”和“写”等。只要是文件,都可以用这套方法操作。Linux 系统提供的文件 I/O 接口函数,是以最基本的系统服务形式提供的,又称它们为基本 I/O 函数。这些函数有个共同的特点:它们都通过文件描述(fd)来完成对指定文件的 I/O 操作。
三、在 C 语言下进行文件 I/O 编程,一般要包含程序如下所列的头文件,这些头文件定义了文件 I/O 用到的数据类型、函数原型及其它要用到的符号常量。
-
#include<sys/types.h> /* 定义数据类型,如 ssize_t,off_t 等 */
-
#include <fcntl.h> /* 定义 open,creat 等函数原型,创建文件权限的符号常量 S_IRUSR 等 */
-
#include <unistd.h> /* 定义 read,write,close,lseek 等函数原型 */
-
#include <errno.h> /* 与全局变量 errno 相关的定义 */
-
#include <sys/ioctl.h> /* 定义 ioctl 函数原型 */
-
-
int open(const char *pathname, int flags);
-
int open(const char *pathname, int flags, mode_t mode);
-
-
int creat(const char *pathname, mode_t mode);
操作成功,返回值为文件描述符 fd,否则返回-1,同时设置全局变量 errno 报告具体错误的原因。
参数 打开文件标识 含义
pathname - C 字符串形式的文件名
O_RDONLY 以只读方式打开文件,与 O_WRONLY 和 O_RDWR 互斥
O_WRONLY 以只写方式打开文件,与 O_RDONLY 和 O_RDWR 互斥
flags O_RDWR 以可读写方式打开文件,与 O_WRONLY 和 O_RDONLY 互斥
O_CREAT 如果要打开的文件不存在,则创建该文件
O_EXCL 该标志与 O_CREAT 共同使用时,会去检查文件是否存在,若文件不存在则创建该文件,否则将导致打开文件失败。此外,打开文件链接时,使用该标志将导致失败
O_NOCTTY 如果要打开的文件为终端设备,则不把该终端设备当成控制终端
O_TRUNC 若文件存在且以可写方式打开,此标志会清除文件内容,并将其长度置为 0
O_APPEND 读写文件都从文件的尾部开始,所写入的数据会以追加的方式插入到文件末尾
O_NONBLOCK 以不可阻塞方式打开文件,也就是不管有无数据需要读写或者等待,都会立即返回
mode - 创建文件的权限模式,可以使用八进制数来表示新文件的权限,也可采用中定义的符号常量。当打开已有文件时,将忽略这个参数。
创建文件的权限模式
符号常量 值 含义 符号常量 值 含义
S_IRWXU 0x700 所属用户读、写和执行权限 S_IRWXG 0x070 组用户读、写和执行权限
S_IRUSR 0x400 所属用户读权限 S_IRGRP 0x040 组用户读权限
S_IWUSR 0x200 所属用户写权限 S_IWGRP 0x020 组用户写权限
S_IXUSR 0x100 所属用户执行权限 S_IXGRP 0x010 组用户执行权限
S_IRWXO 0x007 其他用户读、写和执行权限 S_IWOTH 0x002 其他用户写权限
S_IROTH 0x004 其他用户读权限 S_IXOTH 0x001 其他用户执行权限
creat()创建文件时,如果文件已存在,则会把已存在的文件内容清空、长度截为 0,然后返回对应的文件描述符;如果文件不存在,则直接创建,然后返回创建文件的描述符;
当 open()的参数 flags 设置了 O_CREAT 时,如果文件已存在,则直接打开并返回文件描述符;如果文件不存在,则创建新文件,然后返回对应的文件描述符。
-
int close(int fd);
如果文件顺利关闭,返回 0,否则返回-1,同时设置全局变量 errno 报告具体错误的原因
-
ssize_t read(int fd, void *buf, size_t count);
操作成功,返回实际读取的字节数,如果已到达文件结尾,返回 0,否则返回-1 表示出错,同时设置全局变量 errno 报告具体错误的原因。
参数 fd 是所打开文件的描述符,buf 是数据缓冲区,存放着准备读入文件的数据,count是请求写入的字节数。实际读取的字节数,可以小于请求的字节数 count,比如下面两种情况:
-
文件长度小于请求的长度,即还没达到请求的字节数时,就已到达文件结尾。
-
读设备文件时,有些设备每次返回的数据长度小于请求的字节数,如终端设备一般按行返回,即每读到一行数据,就返回。
-
ssize_t write(int fd, const void *buf, size_t count);
操作成功,返回实际写入的字节数,出错则返回-1,同时设置全局变量 errno 报告具体错误的原因。
参数 fd 是所打开文件的描述符,buf 是数据缓冲区,存放着准备写入文件的数据,count是请求写入的字节数。实际写入的字节数可以小于请求写的字节数。
-
int fsync(int fd);
操作成功返回 0,否则返回-1,同时设置全局变量 errno 报告具体错误的原因。
fsync()函数的功能是进行文件数据同步,强制把已修改过的文件数据存入持久存储设备中。
write()函数一旦返回,表明所写的数据已提交到系统内部缓存了,但此时数据并不一定已经被写入磁盘等持久存储设备中。要确保已修改过的数据全部写入持久存储设备中,正确的做法是调用 fsync 函数进行文件数据同步,强制把已修改过的文件数据写入持久存储设备中。 如果不调用 fsync(),在 write()返回后马上就复位或重新上电,则所作的修改就可能没有被更新,从而造成文件数据丢失。
文件操作实例:
-
#include <sys/types.h> /* 定义数据类型,如 ssize_t, off_t等 */
-
#include <fcntl.h> /* 定义 open,creat 等函数原型,创建文件权限的符号常量 S_IRUSR 等 */
-
#include <unistd.h> /* 定义 read,write,close,lseek 等函数原型 */
-
#include <errno.h> /* 与全局变量 errno 相关的定义 */
-
#include <sys/ioctl.h> /* 定义 ioctl 函数原型 */
-
#include <iostream>
-
-
using std::cout;
-
using std::endl;
-
-
int main(void)
-
{
-
char filename[] = "sample.txt";
-
char str[] = "file sample, hello wolrd!\n";
-
int fd = -1;
-
int res = 0;
-
char buf[128] = {0};
-
-
fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH | S_IRGRP | S_IWGRP);
-
-
if (fd < 0)
-
{
-
cout << "open \"" << filename << "\"" << " file failed" << std::endl;
-
return -1;
-
}
-
cout << "open \"" << filename << "\"" << " successful" << endl;
-
-
res = write(fd, str, sizeof(str));
-
cout << "write " << res << " bytes to " << "\"" << filename << "\"" << endl;
-
fsync(fd);
-
cout << "data fsysc to file" << endl;
-
close(fd);
-
cout << "close file" << endl;
-
-
fd = open(filename, O_RDONLY);
-
if (fd < 0)
-
{
-
cout << "open \"" << filename << "\"" << " file failed" << std::endl;
-
return -1;
-
}
-
-
res = read(fd, buf, sizeof(buf));
-
buf[res] = '\0';
-
cout << "read " << res << " bytes from file " << "\"" << filename << "\", " << buf << endl;
-
close(fd);
-
-
return 0;
-
}
-
#Makefile for file_wr
-
-
EXE = file_wr
-
OBJ = file_wr.o
-
SRC = file_wr.c
-
-
CXX = g++
-
CXXFLAGS = -g
-
LDFLAGS =
-
-
EXE:$(OBJ)
-
$(CXX) $(LDFLAGS) -o $(EXE) $^
-
-
OBJ:$(SRC)
-
$(CXX) $(LDFLAGS) -o $(OBJ) -c $^
-
-
.PHONY:clean
-
clean:
-
-$(RM) -rvf $(OBJ) $(EXE)
在这个范例中,先以可写方式打开当前目录下的“sample.txt”文件,如果该文件不存在,则创建文件,再往文件中写入一个字符串“file sample, hello world!\n”,把操作结果输出到终端后,关闭文件。接着再次以只读模式打开该文件,读取刚才写入的数据,并把结果输出到终端,最后关闭该文件。
阅读(6899) | 评论(0) | 转发(0) |