4

I've got a problem with deleting/overwriting a file using my program which is also being used(read) by my program. The problem seems to be that because of the fact my program is reading data from the file (output.txt) it puts the file in a 'in use' state which makes it impossible to delete or overwrite the file.

I don't understand why the file stays 'in use' because I close the file after use with fclose();

this is my code:

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
  }
}

I use fclose() to close the file but the file remains in use by my program until my program is totally shut down.

What is the solution to free the file so it can be deleted/overwrited?

In reality my code isn't a loop without an end ; )

Thanks in advance!

Marco

Update

Like ask a part of my code which also generates the file 'in use'. This is not a loop and this function is being called from the main();

Here is a piece of code:

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);

}

The while loop parses the file. The output.txt contains sets of 9 variables, the number of sets is unknown but always in sets of 9.

output.txt could contain for example: 0,1,2,3,4,5,6,7,8,8,7,6,5,4,1,2,3,0

update 2

code:

    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
    }
}

sorry for using pre again but I don't get the formatting of this site :(

Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
Marco
  • 41
  • 1
  • 1
  • 4
  • 1
    Do you use strerror/perror to get diagnostics about what went wrong? What OS are you on? – Henno Brandsma Jan 12 '11 at 08:56
  • Have you already tried to fflush() the file before fclose()ing it? – Bart Jan 12 '11 at 08:56
  • @Bart, that's not necessary, `flcose()` will take care of that. @Marco, as @Henno Brandsma says, inspect the `errno` and see what it says, this may give you some clues. On a side note, this is tagged C++, why aren't you using IO streams?? – Nim Jan 12 '11 at 09:06
  • You always need to check `fclose()` return value. – Simone Jan 12 '11 at 09:07
  • Thank you for those quick answers. My OS is Windows XP (pro). I haven't tried fflush() beacause of what Nim says. I will try to figure out what errno says. I ain't to skilled in c++ programming, so thats the reason why I chose this method. How about IO Streams? Whats the difference? – Marco Jan 12 '11 at 09:07
  • 1
    As he's reading the file, would there be a need to call `fflush` anyway? – Moo-Juice Jan 12 '11 at 09:08
  • @Simone it's pretty useless (unless for debugging) because you can't do anything meaningful with that. it's like throwing from a destructor. – Yakov Galka Jan 12 '11 at 09:10
  • I tried fflush() before fclose() bit this didn't solve the problem. – Marco Jan 12 '11 at 09:13
  • Can you please post the code (if possible, summarize if necessary) that is between the open and close? I noticed you're running this in a loop. Is this happening on the 1st or a subsequent iteration? – Moo-Juice Jan 12 '11 at 09:16
  • In my program there is a first section of code which isn't in a loop there also is a fopen()/fclose() part but when i only run this part, the same thing happens. I will try to post this part of code. – Marco Jan 12 '11 at 09:18
  • Usually you can't remove a file only if it's still opened by another process, maybe the same that creates the output.txt you're trying to read. We absolutelly need to see the code. – Mr.Gate Jan 12 '11 at 09:23
  • @Marco: You should use the `{}` button instead of pre. – Yakov Galka Jan 12 '11 at 09:33
  • There's no reason to do fflush() on a file you're just reading. fflush() could be called before fclose() in your runProgram() function. There's something in my mind that tells me you actually run another program, living it's own life, to build and feed output.txt file. So... you probably try to delete that file while it's still opened by the program that builds it since running a program could be done without waiting for that program to end. – Mr.Gate Jan 12 '11 at 09:47
  • @ybungalobill it seems that the OP is debugging, isn't it? – Simone Jan 12 '11 at 09:58
  • @Mr.Gate: That's not the problem as sorted out below; – Marco Jan 12 '11 at 10:42

5 Answers5

1

There is probably other places in your code where you don't call fclose, leaking the file. Even in this code, if an error occurs between fopen and fclose (or a return statement, or a continue statement, etc...) you'll leak the file. Please, switch to RAII idiom.

Edit: include this into your code:

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; 
}

and replace each

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

with:

PoorMansFile file(str1, str2);

Tell us if it helps;

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • I've checked my code but after every time I open the file, I also close it. What do you mean with RAAI idiom? – Marco Jan 12 '11 at 09:16
  • 1
    "I've checked my code but after every time I open the file, I also close it" It's a very naive statement. see [RAII](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) or any good C++ book. basically, switch to std::fstream. – Yakov Galka Jan 12 '11 at 09:21
  • @Marco, RAII stands for *R*esource *A*quisition *I*s *I*initalization. It basically means that if you have an object that has resources, constructing it is enough to use those resources. Hence, ybungalobill's suggestion of using `std::fstream`. – Moo-Juice Jan 12 '11 at 09:23
  • It compiles without errors, but when I run the compiled executable it gives the following error: Debug assertion faild! with a path shown to fclose.c. Expression: (stream != NULL). This has something to do with the int fclose() we declare? – Marco Jan 12 '11 at 09:58
  • @Marco: have you included the overload of fclose? – Yakov Galka Jan 12 '11 at 10:01
  • @ybungalobill: I don't exactly understand what you mean? How do I do that? – Marco Jan 12 '11 at 10:11
  • @Marco: just paste it into your code. I've edited it after my first edit, so make sure it's the last version. – Yakov Galka Jan 12 '11 at 10:15
  • I've pasted it into my source and it compiles with succes. Program also runs like usual but still the output.txt isn't editable/deletable while my program is running. Still many thanks for trying :D – Marco Jan 12 '11 at 10:20
  • @Marco: Nice. now we are **sure** that you're not leaking the file. – Yakov Galka Jan 12 '11 at 10:30
  • @ybungalobill: Yes, nice. Now what to do? What we do know is that fopen() and fclose() is causing it because just those to function without any code between it already keep the file occupied. See above posts. – Marco Jan 12 '11 at 10:33
  • I've done this piece of fstream: ifstream file; file.open("file.txt"); file.close(); and between open and close the file isn't modifiable but after close() it is. So fstream could work for me, I'm only not known with it so it should study on how to read/write files with it. Still, I do want to know why fopen()/fclose() is causing the problem I've got. – Marco Jan 12 '11 at 10:40
1

Will it be due to maximum disk space has been reached and there's still data in the file streams buffer; fclose'ing a file stream flushes it (writes all the data in the buffer), the write operation will fail since maximum disk space is reached.

I suggest you to scope down the problem, by calling fclose() directly after fopen(). If it success, then something is wrong in the code between fclose() and fopen().

wengseng
  • 1,330
  • 1
  • 14
  • 27
  • Concerning disk space, there is plenty (34GB); Thats a goog one, I will try fclose() directly after fopen(); – Marco Jan 12 '11 at 10:06
  • fclose() directly after fopen() results in the same problem, nothing wrong with my code in between. – Marco Jan 12 '11 at 10:09
  • @Marco then as my answer suggested, the program generating `output.txt` probably has not finished. – Moo-Juice Jan 12 '11 at 10:11
  • @Moo-Juice: I think it is finished, because when I run the program manually, without the use of my program, and let it run as soon as the output.txt is generated I can manually edit/delete it. So this is even possible WHILE the program is running. It really comes down to flcose/fopen – Marco Jan 12 '11 at 10:23
  • @Marco: "fclose() directly after fopen() results in the same problem" what if you remove them completely? – Yakov Galka Jan 12 '11 at 10:49
  • Interesting. When I only do runProgram(); the file is also locked (so I did a wrong assumption that manually running the program results in the same as runProgram() in my program). I will update the code above with waht runProgram() contains. – Marco Jan 12 '11 at 10:55
  • @ybungalobill: Above found my runProgram() function with program execution and termination in it. It probably isn't the best way but I'm not a pro. I will try to find out if the program 'program.exe' I'm using has a way to terminate itself in a good way and thus correctly releasing output.txt. It is possible to implement c-code in this program. Anybody an idea how to let a program terminate itself using c-code? OS: windows xp pro. – Marco Jan 12 '11 at 11:08
  • @Marco: It's interesting! Did you try to check the return value of fopen() and fclose()? Verify them according to MSDN... And also change the file format(like output.dat) and read/write mode. Do let us know the latest findings... – wengseng Jan 13 '11 at 13:18
0

The file could still be in use by the CRT or OS - for example, the OS may buffer writes to the disk. fflush() will only flush CRT buffers, not OS buffers.

Puppy
  • 144,682
  • 38
  • 256
  • 465
0

Just a shot in the dark here...

What is inside runProgram()? Does that function wait until the program has finished before returning? I wonder if the program that is writing the data is, in fact, still running... it's difficult to tell from here, but thought I'd throw it out there!

Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
  • inside runProgram() is use ShellExecute() to start a program; this program generates output.txt and the simplest way to check if the program can be terminated(system("taskkill")) is to check if output.txt exists(the program doens't shut down after generation and this cannot be changed). And thats where the problem is right now. The first run ther isn't a output.txt so everything goes ok. But after the first run output.txt should be deleted to make the second run go ok. But I can't delete output.txt because it is in use. – Marco Jan 12 '11 at 10:03
  • @Marco, just because the file exists doesn't mean it is closed or that the program has finished running... – Moo-Juice Jan 12 '11 at 10:04
  • Of course, the file exist as well as you open it so the first time you run ShellExecute() of the program that build the file the file is there for you. As soon as you start reading it, the writing program is still operating. Probably the reading program hits the end of the file while it's still used by the program you call so you can't remove it. Try this: a) the program that creates the output.txt file opens 'o.txt' file and write in it. b) when the program terminates, close the 'o.txt' file and rename it in 'output.txt'. c) Now you reading program shoul not have problem to remove it! – Mr.Gate Jan 12 '11 at 10:07
  • I already tried something like that. In this case it isn't the program that generates output.txt that keeps it occupied, it's my own program and being cause by fopen() & fclose(). See comments @wengseng – Marco Jan 12 '11 at 10:16
-1

After reading all answers and comments I could not think of any reason of OP's problem.

Is this multi threaded or reentrant routine?

What will happen if fopen twice and fclose twice on the same file? Is this could be the cause of the problem?

In this thought I suggest two more checks.

  • printf all fopen/fclose call
  • after fclose reset file variable to NULL

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

If you are inconvenient with printf debugging you can use OutputDebugString.

extern void __stdcall OutputDebugStringA(const char*) (MS VC only)

9dan
  • 4,222
  • 2
  • 29
  • 44