微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 C++ 中正确打开和关闭文件?

如何解决如何在 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 中输出通道的指针,然后我用我的文件替换屏幕并关闭不需要的。

  1. 我的代码是正确的,但我是否忘记了其他任何东西,或者可以让它更短/更清晰吗?

  2. 最重要的是,如果一行失败,我想返回 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);

您必须检查 filenodupopen 的返回结果,以确保您的程序没有遇到对其施加的某些限制,并且 errno变量会告诉你一个原因。在其他一些平台上,例如 Windows,确实存在更合适的错误报告功能。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。