【问题标题】:close file with fclose() but file still in use使用 fclose() 关闭文件但文件仍在使用中
【发布时间】:2011-01-12 08:51:12
【问题描述】:

我在使用我的程序删除/覆盖文件时遇到问题,我的程序也在使用(读取)该文件。问题似乎是因为我的程序正在从文件(output.txt)中读取数据,它会将文件置于“使用中”状态,从而无法删除或覆盖文件。

我不明白为什么文件一直处于“使用中”,因为我在使用 fclose() 后关闭了文件;

这是我的代码:

bool bBool = true

while(bBool){
  //Run myprogram.exe tot generate (a new) output.txt

  //Create file pointer and open file
  FILE* pInputFile = NULL;
  pInputFile = fopen("output.txt", "r");
  //
  //then I do some reading using fscanf()
  //
  //And when I'm done reading I close the file using fclose()
  fclose(pInputFile);

  //The next step is deleting the output.txt
  if( remove( "output.txt" ) == -1 ){
    //ERROR
  }else{
    //Succesfull
  }
}

我使用 fclose() 关闭文件,但我的程序仍在使用该文件,直到我的程序完全关闭。

释放文件以便可以删除/覆盖的解决方案是什么?

实际上我的代码不是一个没有结束的循环; )

提前致谢!

马可

更新

就像询问我的代码的一部分,它也会生成“正在使用”的文件。这不是一个循环,这个函数是从 main() 调用的;

这是一段代码:

int iShapeNr = 0;

void firstRun()
{
    //Run program that generates output.txt
    runProgram();

    //Open Shape data file
    FILE* pInputFile = NULL;
    int iNumber = 0;
    pInputFile = fopen("output.txt", "r");

    //Put all orientations of al detected shapes in an array
    int iShapeNr = 0;
    int iRotationBuffer[1024];//1024 is maximum detectable shapes, can be changed in RoboRealm
    int iXMinBuffer[1024];
    int iXMaxBuffer[1024];
    int iYMinBuffer[1024];
    int iYMaxBuffer[1024];

    while(feof(pInputFile) == 0){       
        for(int i=0;i<9;i++){
            fscanf(pInputFile, "%d", &iNumber);
            fscanf(pInputFile, ",");
            if(i == 1) {
                iRotationBuffer[iShapeNr] = iNumber;
            }
            if(i == 3){//xmin
                iXMinBuffer[iShapeNr] = iNumber;
            }
            if(i == 4){//xmax
                iXMaxBuffer[iShapeNr] = iNumber;
            }
            if(i == 5){//ymin
                iYMinBuffer[iShapeNr] = iNumber;
            }
            if(i == 6){//ymax
                iYMaxBuffer[iShapeNr] = iNumber;
            }
        }
        iShapeNr++;
    }
    fflush(pInputFile);
    fclose(pInputFile);

}

while 循环解析文件。 output.txt 包含 9 个变量的集合,集合的数量未知,但总是以 9 个为一组。

output.txt 可以包含例如:0,1,2,3,4,5,6,7,8,8,7,6,5,4,1,2,3,0

更新 2

代码:

    void runProgram(){
    //Check if output.txt exists, if so delete it
    if(fileExists("output.txt") == 1){
        //Delete output.txt
        if( remove( "output2.txt" ) == -1 ){
            //errormessage
        }else{
            //succesfull
        }
    }   
    //start program
    ShellExecute( NULL, TEXT("open"), TEXT("program.exe"), NULL, NULL, SW_SHOWMAXIMIZED);

    while(fileExists("output.txt") == 0);

    //Close program
    int iCheck = system("taskkill /IM program.exe");
    if(iCheck != 0){
        //error could not shut down
    }
}

很抱歉再次使用 pre 但我没有得到这个网站的格式:(

【问题讨论】:

  • 您是否使用 strerror/perror 来诊断问题所在?你在什么操作系统上?
  • 您是否在 fclose() 之前尝试过 fflush() 文件?
  • @Bart,这不是必需的,flcose() 会解决这个问题。 @Marco,正如@Henno Brandsma 所说,检查errno 并查看它的内容,这可能会给你一些线索。顺便说一句,这是标记为 C++,你为什么不使用 IO 流??
  • 你总是需要检查fclose()返回值。
  • 他在读文件的时候,有必要打电话给fflush吗?

标签: c++ file-io fclose


【解决方案1】:

会不会是因为已达到最大磁盘空间而文件中仍有数据 流缓冲区; fclose'ing 文件流会刷新它(将所有数据写入缓冲区),由于达到最大磁盘空间,写入操作将失败。

我建议您通过在 fopen() 之后直接调用 fclose() 来缩小问题的范围。 如果成功,则说明 fclose() 和 fopen() 之间的代码有问题。

【讨论】:

  • 关于磁盘空间,有很多(34GB);那是一个goog,我会在fopen()之后直接尝试fclose();
  • fclose() 直接在 fopen() 之后导致同样的问题,我的代码在两者之间没有问题。
  • @Marco 然后正如我的回答所建议的那样,生成output.txt 的程序可能还没有完成。
  • @Moo-Juice:我认为已经完成了,因为当我手动运行程序时,不使用我的程序,并且一生成 output.txt 就让它运行我可以手动编辑/删除它。所以这在程序运行时甚至是可能的。它真的归结为 flcose/fopen
  • @Marco: "fclose() 直接在 fopen() 之后会导致同样的问题" 如果你完全删除它们会怎样?
【解决方案2】:

您的代码中可能还有其他地方没有调用fclose,从而导致文件泄漏。即使在此代码中,如果 fopen 和 fclose (或 return 语句,或 continue 语句等)之间发生错误,您也会泄漏文件。请切换到 RAII 成语。

编辑:将其包含到您的代码中:

struct PoorMansFile {
    FILE *_file;
    PoorMansFile(const char* str1, const char* str2) : _file(fopen(str1,str2)) {}
    ~PoorMansFile() { if(_file) fclose(_file); }
    operator FILE*() const { return _file; }
};
int fclose(PoorMansFile& file)
{ 
    if(!file) 
        return 0;

    int t = fclose(file._file);
    file._file = 0; 
    return t; 
}

并替换每个

FILE* file = NULL;
file = fopen(str1, str2);

与:

PoorMansFile file(str1, str2);

如果有帮助,请告诉我们;

【讨论】:

  • 我检查了我的代码,但每次打开文件后,我也会关闭它。 RAAI 成语是什么意思?
  • “我检查了我的代码,但每次打开文件后,我也关闭它”这是一个非常幼稚的说法。请参阅RAII 或任何好的 C++ 书籍。基本上,切换到 std::fstream。
  • @Marco, RAII 代表 Resource Aquisition Is Iinitialization .这基本上意味着,如果您有一个具有资源的对象,则构建它就足以使用这些资源。因此,ybungalobill 建议使用std::fstream
  • 它编译没有错误,但是当我运行编译后的可执行文件时,它给出了以下错误:调试断言失败!显示到 fclose.c 的路径。表达式:(流!= NULL)。这和我们声明的 int fclose() 有关系吗?
  • @Marco:你是否包含了 fclose 的重载?
【解决方案3】:

CRT 或操作系统可能仍在使用该文件 - 例如,操作系统可能会缓冲对磁盘的写入。 fflush() 只会刷新 CRT 缓冲区,而不是操作系统缓冲区。

【讨论】:

  • @Marco:那将是特定于操作系统的。
【解决方案4】:

这里只是在黑暗中拍摄......

runProgram() 里面是什么?该函数是否等到程序完成后再返回?我想知道正在写入数据的程序实际上是否仍在运行……从这里很难判断,但我想我会把它扔掉!

【讨论】:

  • 里面的runProgram()是使用ShellExecute()来启动一个程序;该程序生成 output.txt,检查程序是否可以终止的最简单方法(system("taskkill"))是检查 output.txt 是否存在(生成后程序不会关闭,并且无法更改) .这就是问题所在。第一次运行不是 output.txt,所以一切正常。但是在第一次运行之后,应该删除 output.txt 以使第二次运行正常。但我无法删除 output.txt,因为它正在使用中。
  • @Marco,文件存在并不意味着它已关闭或程序已完成运行......
  • 当然,文件在您打开时就存在,所以当您第一次运行构建文件的程序的 ShellExecute() 时,该文件就在那里。一旦你开始阅读它,写作程序仍在运行。读取程序可能会到达文件末尾,而您调用的程序仍在使用它,因此您无法将其删除。试试这个: a) 创建 output.txt 文件的程序打开 'o.txt' 文件并在其中写入。 b) 当程序终止时,关闭“o.txt”文件并在“output.txt”中重命名。 c) 现在你阅读程序应该没有问题了!
  • 我已经尝试过类似的方法。在这种情况下,它不是生成 output.txt 的程序,而是我自己的程序,并且是由 fopen() 和 fclose() 引起的。见 cmets @wengseng​​span>
【解决方案5】:

在阅读了所有答案和 cmets 后,我想不出 OP 问题的任何原因。

这是多线程还是可重入例程?

如果在同一个文件上两次 fopen 和 fclose 两次会发生什么?这可能是问题的原因吗?

在这个想法中,我建议再进行两次检查。

  • printf 所有 fopen/fclose 调用
  • fclose 后将文件变量重置为 NULL

f = fopen("", ""); printf("fopen => %p", f);
f关闭(f); printf("fclose => %p", f); f = 0;

如果您不方便使用 printf 调试,您可以使用 OutputDebugString。

extern void __stdcall OutputDebugStringA(const char*)(仅限 MS VC)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-26
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 2021-02-02
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多