如您所见,该程序有两个文件指针sport和fruit指向文件fruit.txt。问题是运行程序后,sport.txt为空,fruit.txt包含中文字符。我期望sport.txt应该包含单词“basketball”,因为它在重定向发生之前写入文件。那么,这里有什么问题?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include "../cus_header/cus_header.h"
int main(){
FILE *fruit = fopen("fruit.txt", "w");
if(!fruit)
error("cannot open fruit.txt");
FILE *sport = fopen("sport.txt", "w");
if(!sport)
error("cannot open sport.txt");
int de_sport = fileno(sport);
int de_fruit = fileno(fruit);
printf("file number of sport.txt: %i and of fruit.txt: %i\n", de_sport, de_fruit);
fwrite("basketball", sizeof(char), 10, sport);
fwrite("apple", sizeof(char), 6, fruit);
if(dup2(de_fruit, de_sport) == -1)
error("cannot redirect");
fwrite("basketball", sizeof(char), 10, sport); //???
fwrite("apple", sizeof(char), 6, fruit); // ???
fclose(sport);
fclose(fruit);
return 0;
}
答案 0 :(得分:0)
正如评论已经提到的那样,您不应该将文件操作与流(使用FILE*
,fopen
,fwrite
,fclose
)混合使用原始文件操作(使用文件描述符,open
,write
,close
,dup2
)。特别是不要像在这段代码中那样将它们混合在同一个文件指针/描述符上。
让我们浏览一下代码,了解它的行为方式:
FILE *fruit = fopen("fruit.txt", "w");
...
FILE *sport = fopen("sport.txt", "w");
你不应该关心FILE
结构的外观,让我们假设它将底层文件描述符放在某处。
int de_sport = fileno(sport);
int de_fruit = fileno(fruit);
您创建的局部变量包含与两个FILE*
引用相同的文件描述符。
fwrite("basketball", sizeof(char), 10, sport);
fwrite("apple", sizeof(char), 6, fruit);
你在两个文件中都写了些东西。由于默认情况下C文件流是缓冲的,因此磁盘上文件中的实际写入可能不会立即发生(在您的情况下它不会发生)。
dup2(de_fruit, de_sport)
这会关闭文件描述符de_sport
并使其引用与de_fruit
相同的文件。实际数值保持不变,只更改它们引用的实际文件。这意味着在FILE
调用后,两个dup2
句柄将写入同一文件。
fwrite("basketball", sizeof(char), 10, sport); //???
fwrite("apple", sizeof(char), 6, fruit); // ???
这将写入相同的底层文件,因为这两个描述符现在引用同一个文件。但同样,因为流被缓冲,实际上这可能只是附加到这两个FILE*
的缓冲区。
fclose(sport);
fclose(fruit);
这会刷新缓冲区,因此实际写入磁盘就在这里。因为描述符已被更改,如果直到现在都没有发生刷新,则两个流实际上将刷新到磁盘上的同一文件。
这可能就是您看到这种行为的原因,但请记住,您所做的事情并不安全,行为或文件内容可能会有所不同。