文件描述符操作
复制文件描述符
Linux环境下使用dup和dup2函数复制一个文件描述符,dup和dup2函数原型:
#include<unistd.h>
int dup(int filedes);
int dup2(int filedes,int filedes2);
dup 应用实例:判断当前进程第一个可用的文件描述符方法(展示错误的方法和正确的方法)
错误方法:由于文件表共享,下面利用dup函数判断是错误的,程序的错误在于如果关闭fd所代表的文件,那么标准输入同时也被关闭了,
因为此2个文件共用一个文件表项;
#include<unistd.h>
int first_avail_fd(){
int fd;
fd=dup(0);//复制任意一个已知打开的文件,标准输入几乎都要打开的
close(fd);
return fd;
}
正确方法:使用open打开,然后关闭
#include<unistd.h>
int first_avail_fd(){
int fd;
fd=open("test.txt",O_RDONLY);//打开一个肯定存在的文件,open函数会返回第一个可用的fd
close(fd);//关闭改文件,使得第一个可用fd变得再次可用
return fd;
}
dup2函数: dup2函数和dup类似,不过dup2函数允许用户使用第2个参数指定将文件描述符复制到哪一个文件描述符上(dup2实际上应该读成dupto而不是duptwo)
说明:
- 该操作表示将fd1复制到fd2上,并且返回fd2的值。如果fd2已经打开,则将fd2所代表的文件关闭,再将fd1复制到fd2;
- 如果fd = dup2(fd1,fd1),该种使用是很危险的,在复制时会关闭fd1所代表的文件,这时复制过来的fd1文件描述符将是一个无意义的值,对其操作会导致程序的错误。所以在使用dup2函数时应做以下判断:
if(fd1 != fd2)
fd=dup2(fd1,fd2);
I/O重定向概念及其应用
重定向概念: 重定向的概念就是使用一个文件代替系统默认的标准输入、标准输出和标准出错。例如,使用test.txt文件进行重定向输入,就是用test.txt 代替原来的标准输入。这时应用程序不再从键盘输入中读取输入内容,而是从test.txt 文件中读取输入内容。同样,使用test.txt 文件重定向标准输出,就是使用test.txt文件代替原来的标准输出。这时应用程序会将输出的内容输出到文件test.txt中。
重定向方法:
- <、> 在shell中实现:< filename表示输入重向;> filename表示输出重向; 2>filename表示标准出错重向;
应用案例:
功能说明: 通过重定向实现文件的输入输出,在编程过程中I/O重定向也是很有用的,下面实例演示了-一个I/O重定向的应用,该程序需要从input.txt文件中读入10个数据,并且找出其中的最大值,并且将该最大值输出到res.txt文件中。该程序编写过程中并不直接进行文件操作,而是将对文件操作的细节交给I/O重定向进行处理
#include<stdio.h>
#define MAX 10
int main(void){
int array[MAX];
int max;
int i;
for(i=0;i<MAX;i++){
scanf("%d",&array[i]);
}
max=array[0];
for(i=0;i<MAX;i++){
if(max<array[i])
max=array[i];
}
printf("the result is %d\n",max);
return 0;
}
使用说明:
(1)编译后,在shell中运行,可直接打印出结果
(2)使用重定向方法,先在input.txt中存入10个数,然后在shell中输入:
./get_max <input.txt >res.txt
注意: 此方法优点是编程简单,但是使用复杂,还可以将重定向的命令写入一个shell脚本!当然这种依赖于shell,如果系统中没有shell,则应使用系统接口实现文件操作.
//shell脚本 start.sh
#!/bin/bash
./get_max <input.txt >res.txt
运行shell脚本:./start.sh
控制文件
linux使用fcntl函数进行文件属性操作,函数原型为:
#include<fcntl.h>
int fcntl(int filedes,int cmd,...);
参数说明:
- filedes:表示需要进行属性的文件描述符,文件必须是一个已经打开的文件;
- cmd:表示fcntl函数的可以执行的命令,每一个命令代表一个不同的功能,这些命令有10个,分为5种不同的功能;
- 第三个参数:通常是一个整数,其意义根据第二个参数来
- 返回值:和具体的命令有关
修改打开文件的状态
场景说明: fcntl命令中比较常用的是设置文件状态标志的命令F_ GETFL,以及获得文件状态标志的命令F_ SETFL。由于文件的状态标志在调用open函数打开文件时已经确定,当需要修改这些标志时就只能调用fcntl 函数。但是,并不是所有的文件状态标志都可以被fcntl函数修改,下表列出了文件的状态标志以及其是否能被fcntl函数修改。
应用实例:
功能说明:” 下面实例演示了使用fcntl 函数更改文件的状态标志。该程序首先打开-一个文件,之后使用fentl函数将文件的状态标志修改为追加写,向文件中写的内容追加到文件的结尾。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
int fd;
int flag;
char *p = "1st linux"; /* 测试使用的字符串 */
char *q = "2nd linux";
fd = open("test.txt", O_WRONLY); /* 该文件只写打开 */
if(fd == -1){
perror("fail to open");
exit(1);
}
if(write(fd, p, strlen(p)) == -1){ /* 输入新内容,该内容会覆盖部分旧的内容 */
perror("fail to write");
exit(1);
}
flag = fcntl(fd, F_GETFL, 0); /* 先使用F_GETFL命令得到文件状态标志 */
if(flag == -1){
perror("fail to fcntl");
exit(1);
}
flag |= O_APPEND; /* 将文件状态标志添加"追加写"选项 */
if(fcntl(fd, F_SETFL, flag) == -1){ /* 将文件状态修改为追加写 */
perror("fail to fcntl");
exit(1);
}
if(write(fd, q, strlen(q)) == -1){ /* 再次输入新内容,该内容会追加在旧内容的后面 */
perror("fail to write");
exit(1);
}
close(fd); /* 关闭文件 */
return 0;
}