LINUX系统编程之文件
文件描述符:
1、对于内核而言,所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或者创建一个新文件时,内核向进程返回一个文件描述符。当读写一个文件时,用open和 creat返回的文件描述符标识该文件,将其作为参数传递给read和 write
按照惯例, UNIX shell使用文件描述符0与进程的标准输入相结合,文件描述符1与标准输出相结合,文件描述符2与标准错误输出相结合STDIN_FILENO、 STDOUT_FILENO、 STDERR_FILENO这几个宏代替了0、1、2这几个模数。
2、文件描述符,这个数字在一个进程中表示一个特定含义,当我们openー个文件时,操作系统在内存中构建了一些数据结构来表示这个动态文件,然后返回给应用程序一个数字作为文件描述符,这个数字就和我们内存中维护的这个动态文件的这些数据结构绑定上了,以后我们应用程序如果要操作这个动态文件,只需要用这个文件描述符区分。
3、文件描述符的作用域就是当前进程,出了这个进程文件描述符就没有意义了。
1、open():打开或创建一个文件
头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
使用形式(int表示其返回值为整型,使用的时候不用写):
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
参数说明:
Pathname:要打开的文件名(含路径,缺省为当前路径)
Flags:
O_RDONLY 只读打开 O_WRONLY 只写打开 O_RDWR 可读可写打开
当我们附带了权限后,打开的文件就只能按照这种权限来操作。
以上这三个常数中应当只指定一 个。下列常数是可选择的:
O_CREAT: 若文件不存在则创建它。使用此选项时,需要同时说明第三个参数mode,用其说明该新文件的存取许可权限。
O_EXCL: 如果同时指定了OCREAT,而文件已经存在,则出错。
O_APPEND: 每次写时都加到文件的尾端。
O_TRUNC :属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0。
Mode:一定是在flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限
返回值:若成功返回文件描述符,否则返回-1并设置变量errno的值。
学习实例:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main()
{
int fd;
fd = open("./file1",O_RDWR);
if(fd<0){
printf("open file1 fail\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);//0600表示可读可写
if(fd>0){
printf("create file1 success\n");
}
}
return 0;
}
2、close():关闭文件
头文件:
#include <unistd.h>
使用形式:
int close(int fd);
各参数及返回值的含义如下:
fd:要关闭的文件的描述符。
返回值:若成功返回0,出错则返回-1。
*注意:当一个进程终止时,内核会自动关闭它所有打开的文件。
3、creat()创建文件
int creat(const char *filename, mode t mode)
参数说明:
filename:要创建的文件名(包含路径、缺省为当前路径)
mode:创建模式//可读可写可执行
4、write():写文件
头文件:
#include <unistd.h>
定义:
ssize_t write(int fd, const void *buf, size_t count);
参数说明:
fd:要写入的文件的描述符。
buf:要写入的数据所存放的缓冲区。
count:要写入的字节数。
返回值:若成功返回已写的字节数,出错则返回-1并设置变量errno的值。
注意
1:size_t是无符号整型,ssize_t是有符号整型
2:buf指向的内存空间必须事先分配好
学习实例:
#include<sys/stat.h>
#include<fcntl.h>
#include <unistd.h>
#include<string.h>
int main()
{
int fd;
char *buf = "ni hen shuai!";
fd = open("./file1",O_RDWR);
if(fd<0){
printf("open file1 fail\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create file1 success\n");
}
}
printf("open success fd = %d\n",fd);
write(fd,buf,strlen(buf));
close(fd);
return 0;
}
5、read():读文件
头文件:
#include <unistd.h>
使用形式:
ssize_t read(int fd, void *buf, size_t count);
参数说明:
fd:要读取的文件的描述符。
buf:读取到的数据要放入的缓冲区。
count:要读取的字节数。
返回值:若成功返回读到的字节数,若已到文件结尾则返回0,若出错则返回-1并设置变量errno的值。
学习实例:
#include <unistd.h>
#include<string.h>
int main()
{
int fd;
char *buf = "ni hen shuai!";
fd = open("./file1",O_RDWR);
if(fd<0){
printf("open file1 fail\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create file1 success\n");
}
}
printf("open success fd = %d\n",fd);
int n_write = write(fd,buf,strlen(buf));
if(n_write!=-1){
printf("write %d byte to file1\n",n_write);
}
close(fd);
fd = open("./file1",O_RDWR);
char *read_buf;
read_buf= (char *)malloc(sizeof(char)*n_write+1);
int n_read = read(fd,read_buf,n_write);
printf("read %d byte context %s\n",n_read,read_buf);
close(fd);
return 0;
}
6、lseek()文件”光标”位置
头文件:
#include <sys/types.h>
#include <unistd.h>
使用形式:
off_t lseek(int fildes, off_t offset, int whence);
将文件读写指针相对whence移动offset个字节
参数说明:
filder:文件的描述符。
offset:offset个字节(可正可负)
whence:通常是一下三种之一
SEEK_SET:(文件头)将文件偏移量设置在距文件开始处offset个字节。
SEEK_CUR:(文件光标当前位置)将文件偏移量设置在其当前值加offset个字节。
SEEK_END:(文件尾)将文件偏移量设置为文件长度加offset个字节。
返回值:若成功偏移则返回new file offset,若出错则返回-1并设置变量errno的值。
学习实例:
可以将上面read中的例子进行修改,如下:
#include<stdio.h>
#include <stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <unistd.h>
#include<string.h>
int main()
{
int fd;
char *buf = "xie xiong hen shuai!";
fd = open("./file1",O_RDWR);
if(fd<0){
printf("open file1 fail\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create file1 success\n");
}
}
printf("open success fd = %d\n",fd);
int n_write = write(fd,buf,strlen(buf));
if(n_write!=-1){
printf("write %d byte to file1\n",n_write);
}
/*close(fd);
fd = open("./file1",O_RDWR);*/
char *read_buf;
lseek(fd,0,SEEK_SET);//将文件关闭重新打开使光标位于文件头的方式改成使用lseek来移动的形式
read_buf= (char *)malloc(sizeof(char)*n_write+1);
int n_read = read(fd,read_buf,n_write);
printf("read %d context %s\n",n_read,read_buf);
close(fd);
return 0;
}
7、标准C库对文件的操作指令
这里有了上面那些函数的学习,对标准C库中文件操作指令的说明就直接使用下面这个例子进行说明:
#include<stdio.h>
#include<string.h>
int main()
{
FILE *fp;
char *write_Buf = "xie xiong hen shuai";
char read_Buf[128] = {0};
//FILE *fopen(const char *pathname, const char *mode);
fp = fopen("file4","w+");
//size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream)
fwrite(write_Buf,sizeof(char),strlen(write_Buf),fp);
//int fseek(FILE *stream, long offset, int whence);
fseek(fp,0,SEEK_SET);
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
fread(read_Buf,sizeof(char)*strlen(write_Buf),1,fp);
printf("read %s\n",read_Buf);
fclose(fp);
return 0;
}
上面的例程中各个函数的使用形式我都体现在代码中,这里我们可以自己学会通过给出的格式来使用对应函数;另外我们在学习Linux时如果遇到一个函数不会用,可以用man命令查看其使用方式和需要的头文件。