如何解决如何在 C++ 中正确打开和关闭文件?
我想打开一些文件,重定向它们的输出,然后回到以前的情况,所以我写道:
int fd = open("test.txt",O_WRONLY | O_CREAT,0666);
dup(1);
dup2(3,1);
close(3);
//call my func() to print in std::cout which will write to test.txt
dup2(4,1);//Close file
我知道默认输入通道在索引 0 中,输出通道(屏幕)在索引 1 中,stderr
在索引 2 中,所以 fd
将获得 3,dup
1 将创建另一个指向索引 4 中输出通道的指针,然后我用我的文件替换屏幕并关闭不需要的。
-
我的代码是正确的,但我是否忘记了其他任何东西,或者可以让它更短/更清晰吗?
-
最重要的是,如果一行失败,我想返回 false 但这将是很多检查,并且在每一个前进步骤中我们都需要关闭更多。我该如何解决这个问题?
如果我想让一切恢复到默认状态失败怎么办?
请注意,我只知道并想使用open,close,dup,dup2
解决方法
最重要的是编写可靠、无错的代码是程序员的职责,这包括彻底的错误检查。错误检查通常涉及大部分代码,尤其是当用户交互是程序的一部分时。但是,如果你想成为/成为一名优秀的程序员,那就没有办法了。
也就是说,很容易(在第一步中)更改您的代码,使其不依赖于特定的文件描述符编号(未测试)。
int fileFd;
int redirectFd1;
int redirectFd2;
fileFd = open( "test.txt",O_WRONLY | O_CREAT,0666 );
redirectFd1 = dup( 1 );
redirectFd2 = dup2( fileFd,1 );
close( fileFd );
//call my func() to print in std::cout which will write to test.txt
dup2( redirectFd1,1 );//Close file
下一步是添加错误检查。
int fileFd;
int redirectFd1;
int redirectFd2;
if ( ( fileFd = open( "test.txt",0666 ) ) == -1 ) {
// open() failed. Do appropriate error handling here...
exit( 1 );
}
if ( ( redirectFd1 = dup( 1 ) ) == -1 ) {
// dup() failed. Do appropriate error handling here...
// Since we arrvied here,fileFd *is* open. So we need to close it.
// But redirectFd1 is *not* open
close( fileFd );
exit(1);
}
if ( ( redirectFd2 = dup2( fileFD,1 ) ) == -1 ) {
// dup() failed. Do appropriate error handling here...
// Since we arrvied here,fileFd *and* redirectFd1 *are* open.
// So we need to close them.
// But redirectFd2 is *not* open
close( fileFd );
close( redirectFd1 );
exit(1);
}
close( fileFd );
//call my func() to print in std::cout which will write to test.txt
if ( dup2( redirectFD1,1 ) == -1 ) {
// dup2() failed. Do appropriate error handling here...
close( redirectFd1 );
}
close( redirectFd1 );
人们可以争论是否需要检查 close( fileFd )
语句中的错误。事实是 open()
成功了,因此 close()
在这里失败是非常不寻常的。也可以争论是否需要检查最后一个 dup2()
的错误。
通常,我会跟踪打开的文件,并在清理例程中出现错误时注意关闭。代码可能如下所示:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int fileFd;
bool fileFdIsOpen = false;
int redirectFd1;
bool redirectFd1IsOpen = false;
int redirectFd2;
bool redirectFd2IsOpen = false;
void cleanup();
int main( int argc,char* argv[] ) {
int stdoutFd = fileno( stdout );
if ( ( fileFd = open( "test.txt",0666 ) ) == -1 ) {
// open() failed. Do appropriate error handling here...
exit( 1 );
}
fileFdIsOpen = true;
if ( ( redirectFd1 = dup( stdoutFd ) ) == -1 ) {
// dup() failed. Do appropriate error handling here...
cleanup();
exit(1);
}
redirectFd1IsOpen = true;
if ( ( redirectFd2 = dup2( fileFd,stdoutFd ) ) == -1 ) {
// dup() failed. Do appropriate error handling here...
cleanup();
exit(1);
}
redirectFd2IsOpen = true;
close( fileFd );
fileFdIsOpen = false;
//call my func() to print in std::cout which will write to test.txt
if ( dup2( redirectFd1,stdoutFd ) == -1 ) {
// dup2() failed. Do appropriate error handling here...
cleanup();
}
cleanup();
exit (0);
}
void cleanup() {
if ( fileFdIsOpen ) {
close( fileFd );
fileFdIsOpen = false;
}
if ( redirectFd1IsOpen ) {
close( redirectFd1 );
redirectFd1IsOpen = false;
}
if ( redirectFd2IsOpen ) {
close( redirectFd2 );
redirectFd2IsOpen = false;
}
}
,
我知道默认输入通道在索引 0 中,输出通道 (screen) 在索引 1 中,stderr 在索引 2 中,所以 fd 将得到 3
这是不确定的,进程可以运行,这些 id 将被更改,并且起始描述符也可能与 stderr+1 不同。此外,在 Linux 上,存在可以在不打开任何进程的情况下创建进程的情况,但这是不同的。
在 C 头文件中 <stdio.h>
定义了那些应该由运行时库初始化的变量。
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
您展示的代码几乎是 C 代码,而不是 C++,但您可以使用 <cstdio>
和 fileno
函数获取描述符
int fileno(FILE *stream);
您必须检查 fileno
、dup
和 open
的返回结果,以确保您的程序没有遇到对其施加的某些限制,并且 errno
变量会告诉你一个原因。在其他一些平台上,例如 Windows,确实存在更合适的错误报告功能。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。