Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to: Ignore a file for deletion if its in use 6

Status
Not open for further replies.

keepingbusy

Programmer
Apr 9, 2000
1,470
GB
Hi all

As part of an app, DBF's are created by simply using:
Code:
tempfile=SYS(3)
USE MYFILE
copy stru to tempfile+'.dbf'
Slight problem is sometimes, the tempfile gets left behind by the user who has either switched off (yes people stll do that) or worse still, a system crash, before the code gets a chance to:
Code:
dele file tempfile+'.dbf'

As SYS(3) generates a random 8 number digit we thought of trying to resolve this using a couple of lines at the start of a PRG such as:
Code:
dele file 1*.*
dele file 2*.*
etc
The only problem with this would be that if one of the sys(3) numbers is already in use by another, you cannot delete it (and obviously wouldn't want to delete it if its in use by another).
This doesn't happen too often, but as I'm sure your aware, over a period of time the 8 digit DBF's build up using valuable disc space.

This app is version 6

Any suggestions guys?

Many thanks
Lee

Visual FoxPro Versions: 6 & 9
Operating System: Windows XP
 
Use ADIR() to create an array of these files, and then delete them using an ASCAN loop that checks the creation date of the file stored in the ADIR array and deletes them ONLY if they are more than 24 hours old.

Mike Krausnick
Dublin, California
 
Or you could attempt to open the file after setting an ON ERROR function to trap the "File in Use" error, then delete it only if you were able to open it.

Mike Krausnick
Dublin, California
 

Lee,

Do these files have to be shared between users? If not, it would be better to create them in the user's temporary files folder. That way, you can delete them to your heart's content without treading on anyone's toes.

Use SYS(2023) to get a path to the user's temp folder.

Another point: If you prefix the filename with a distinctive combination of characters, you will avoid accidently deleting files that don't belong to your application.

For example:

Tempfile = "_LEE_" + sys(3)

You can then delete _LEE_*.*

Hope this helps.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

My sites:
Visual FoxPro (www.ml-consult.demon.co.uk)
Crystal Reports (www.ml-crystal.com)
 
mkrausnick
Thank you for your replies.
Use ADIR() to create an array of these files, and then delete them using an ASCAN loop that checks the creation date of the file stored in the ADIR array and deletes them ONLY if they are more than 24 hours old.
I'm not sure how this works, do you have an example?
There is one in the help file but you mentioned about deleting files that are over 24 hours old....
Your second post mentions:
Or you could attempt to open the file after setting an ON ERROR function to trap the "File in Use" error, then delete it only if you were able to open it.
The problem I see here is that how do I find what files exist? As each file contains an 8 digit number which could be between 10000000 and 99999999 I'm not sure which way to go.

Mike
Thank you for your post
Do these files have to be shared between users? If not, it would be better to create them in the user's temporary files folder
The temp files are stored within a folder that is shared. You also mentioned about changing the temp file name e.g.
Code:
Tempfile = "_LEE_" + sys(3)
I'm still thinking Mike that files are still going to be left behind and when I issue the command
Code:
dele file Tempfile = "_LEE_" + etc
Some files may still be in use or am I missng something?

I'm grateful for the posts

Lee

Visual FoxPro Versions: 6 & 9
Operating System: Windows XP
 

Lee,

I'm still thinking Mike that files are still going to be left behind .... Some files may still be in use or am I missng something?

No, you're not missing anything. My suggestion for adding a prefix to the filename was not directly related to your problem.

If you had been able to use the user's personal temp folder, as per my first suggestion, you would have run the slight risk of deleting files that had nothing to do with your application. By adding the prefix, you would have avoided that risk.

To go back to the original problem ... since you are obliged to use a shared folder, I suggest you revert to Mike Krausnick's suggestion ragarding error trapping.

I know you are using both VFP 6.0 and 9.0. In 9.0, this is very easy:

Code:
TRY
  DELETE FILE *.*
CATCH
  * Do nothing
ENDTRY

In 6.0, it is a bit more difficult:

Code:
LOCAL lcErrorHandler
lcErrorHandler = ON("error")
ON ERROR *    && in effect, ignore any errors
DELETE FILE *.*
ON ERROR &lcErrroHandler  && re-instate error handling

As for Mike's other suggestion, about using ADIR(), I assume he means that you should get the names of all the files in the relevant folder into an array, and then loop through the array, deleting one at a time. But I'm not sure how that would solve the problem. No doubt he'll clarify that himself.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

My sites:
Visual FoxPro (www.ml-consult.demon.co.uk)
Crystal Reports (www.ml-crystal.com)
 
Mike

Your last works fine. I created a tempfile+'.dbf' with SYS(3) and opened that table. I then ran the code together with my previous posting dele file 1*.* etc and as you mentioned, it ignored the in use file. Just a small problem, the last line of your code throws up an error:
Code:
ON ERROR &lcErrroHandler
Message: Unrecognized command verb

My thanks to you

Lee

Visual FoxPro Versions: 6 & 9
Operating System: Windows XP
 
keepingbusy,

The &lcErrorHandler is the way it was meant to be. Mike is saving the current error handling and then restoring it. The only problem is a type-o, try:

&lcErrorHandler

instead of...

&lcErrroHandler

boyd.gif

SweetPotato Software Website
My Blog
 
I'm glad you got a working solution. Thank you for the star. You asled for an example of my first suggestion.

ADIR() returns a four element array:
- Filename
- Size in bytes
- Last mod date
- Last mod time

To delete files more than 1 day old, assuming you can create a file mask to identity all the files, you could do this:
Code:
local x,cPath
DIMENSION x[1]
cPath = "\temp\"
nFiles = aDir(x,cPath+"*.*")   && or in your case, "1*.*" etc.
* nFiles = the number of files returned
FOR i=1 TO nFiles
  if DATE() - x[i,3] > 0       && Files with mod date prior to today
    erase (cPath+x[i,1])
  endif
NEXT i

This method avoids altering the error handler. But Mike Lewis's solution works perfectly well too.

By the way, I use sys(2015) to generate my temp filenames rather than sys(3). The filenames all start with an underscore, making the files much easier to identify.

Mike Krausnick
Dublin, California
 
I wonder if DELETE FILE *.* isn't a bit too dangeous even if you changed to the directory with the files you want to delete. I'd prefer a solution with ERASE with each single file name determined by ADIR().

I'd say if you have 20 files and the 10th is open DELETE FILE *.* may erase the first 9 and then stop with an error, which is of course suppressed by ON ERROR *, but that stops processing files 11 to 20, which could also have been erased.

I didn't test with code, but the general idea of ignoring errors is quite common and okay in cases where you have little code running for which you only expect certain errors you can simply ignore. Since VFP8 TRY...CATCH...FINALLY is implementing this concept much more elegant than bending the ON ERROR error handling back and forth...

Bye, Olaf.
 
mkrausnick

Thank you for the last suggestion and your posts are worthy of the star!

Olaf

I take your point, but I'm thinking as it doesn't happen too often, ignoring the error in this case, seems to be the easiest sollution.
...but that stops processing files 11 to 20
I'm not sure about that. My understanding is that if an open table, lets say starting with 5 (e.g. 56432178.dbf) is in use, the code ignores it and continues on deleting the remaining files starting with 6, 7, 8 etc.

Mike Lewis: Any thoughts or views on this?

Lee

Visual FoxPro Versions: 6 & 9
Operating System: Windows XP
 
I'd like to go back to the whole question of why you need to create actual tables. Are you doing anything here you can't do with cursors and avoid all this trouble?

Tamar
 
Tamar

Another good point. But the app has been established for sometime and recently upgraded. The issue only came to light then. I would be all for using cursors instead of temp files. Maybe during the next upgrade.

Lee [thumbsup]

Visual FoxPro Versions: 6 & 9
Operating System: Windows XP
 

Lee,

My understanding is that if an open table, lets say starting with 5 (e.g. 56432178.dbf) is in use, the code ignores it and continues on deleting the remaining files starting with 6, 7, 8 etc.

If you've got four files beginning with 5, and the third of them is open, doing DELETE FILE 5*.* will correctly delete the first two. When it gets to the third, it will fire an error, and then abandon the entire operation.

In other words, it will start deleting, but when it hits the open file, it will stop. You will end up with two of the four files deleted. (Of course, you can still carry on with deleting 6*.*, etc.)

If you add code to ignore the error (for example, with TRY/ENDTRY), the result is the same -- but you don't see the error message.

By the way, DELETE FILE and ERASE behave the same in this respect.

To avoid this situation, use ADIR() to get the list of files. Loop through the array, applying DELETE FILE or ERASE to each of them individually (rather than with a wildcard). Ignore any "file in use errors" (for example, with TRY/ENDTRY). That way, you will be sure of deleting every file you want to delete, except those that are open.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

My sites:
Visual FoxPro (www.ml-consult.demon.co.uk)
Crystal Reports (www.ml-crystal.com)
 
Hi Mike,

thanks for checking this out, so my fear of aborting the delete operation with the first error was correct.

Bye, Olaf.
 
If you use the ADIR() option, an easy way to skip the files that are in use as you loop through the array is

FOR ....
ON ERROR OK = .F.
DELETE FILE (XXX)
ENDFOR

WHERE .... IS YOUR LOGIC TO LOOP THROUGH THE ARRAY AND XXX IS THE FILE NAME TO DELETE

THEN RESET YOUR ON ERROR TO WHATEVER IT SHOULD BE FOR YOUR NORMAL ERROR TRAPPING

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top