Remove File By Time

I want to remove a new file by time. I have this so far but I am confused about how to add a time constraint to this. Lets make it a file that is 20 seconds or less just for arguments sake. I also know that file time is different from system time to make this more difficult. Any help appreciated!

1
2
3
4
5
6
7
8
if ( !remove("*.txt") )
{
cout<<"Successful deletion";
}
else
{
cout<<"Oops, file not deleted (is it there?)";
}
I'm confused!

Do you want a function that removes all files that are less than 20 seconds old?

Andy

P.S. remove doesn't accept a wildcard. You'll need to use FindFirstFile, etc. and then delete the files you've selected. As you're using WIN32 already, I'd use DeleteFile() rather than remove(). The CRT does provide _findfirst, ... so you could use CRT functions rather than WIN32 calls, but as they're still Windows specific I don't see the point.
Last edited on
Thank you. I will usee find first and Deletefile() but I think the bigfer problem is removing it by time that is the biggest issue I am having.
Last edited on
And yes I do want to remove any file tat is less than 20 seconds old. It should be only one though.
You need to iterate through all the files in your desired directory and get its properties... then decide on the date wether to delete it or not...

check the MSDN for further info
Thank you. Is this closer?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
WIN32_FIND_DATA FindFileData;
HANDLE hFind;

hFind = FindFirstFile(*.*, &FindFileData);
   if (hFind == INVALID_HANDLE_VALUE) 
   {
      printf ("FindFirstFile failed (%d)\n", GetLastError());
      return;
   } 
   else 
   {
      _tprintf (TEXT("The first file found is %s\n"), 
      FindFileData.cFileName);
      DeleteFile(*.*);
      FindClose(hFind);
   }


OR THIS.....
1
2
3
4
5
6
7
8
9
10
11
12
13
14
WIN32_FIND_DATA FindFileData;
HANDLE hFile;
LPFILETIME lpCreationTime;

// Find the file.
hFile = FindFirstFile( *.txt,
GENERIC_READ,
0, NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL );

GetFileTime(hFile, lpCreationTime <= currenttime);
DeleteFile(*.txt);

CloseHandle(hFile);

OR THIS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// FileTime.cpp : Defines the entry point for the console application.
//
#include <string>
#include <vector>
#include <windows.h>
#include <time.h>
#include <map>
//#include <tchar.h>

int GetFileList(const wchar_t *searchkey, std::map<std::wstring, std::wstring> &map)
{
    WIN32_FIND_DATA fd;
    HANDLE h = FindFirstFile(searchkey,&fd);
    if(h == INVALID_HANDLE_VALUE)
    {
        return 0; // no files found
    }
    while(1)
    {
        wchar_t buf[128];
        FILETIME ft = fd.ftLastWriteTime;
        SYSTEMTIME sysTime;
        FileTimeToSystemTime(&ft, &sysTime);
        wsprintf(buf, L"%d-%02d-%02d",sysTime.wYear, sysTime.wMonth, sysTime.wDay);
        map[fd.cFileName] = buf;
        if(FindNextFile(h, &fd) == FALSE)
            break;
    }
    return map.size();
}

void main()
{ 
    std::map<std::wstring, std::wstring> map;
    int count = GetFileList(L"*.*", map);
    // Using const_iterator
    for(std::map<std::wstring, std::wstring>::const_iterator it = map.begin(); 
      it != map.end(); ++it)
    {
       MessageBoxW(NULL,it->first.c_str(),L"One",MB_OK);
	   MessageBoxW(NULL,it->second.c_str(),L"Two",MB_OK);

		//MessageBox(it->first.c_str());
	   //MessageBox(it->second.c_str());
    }
} 
Last edited on
I would follow your last approach. As FindFirstFile / FindNextFile give you the file time, you might as well use that, rather than calling GetFileTime [1]

Note that, according the MSDN's entry for FILETIME:

It is not recommended that you add and subtract values from the FILETIME structure to obtain relative times. Instead, you should copy the low- and high-order parts of the file time to a ULARGE_INTEGER structure, perform 64-bit arithmetic on the QuadPart member, and copy the LowPart and HighPart members into the FILETIME structure.

The FILETIME is in increments of 100-nanosecond, so you can work out how many of these is 20 seconds (compared to to the value you obtain using GetSystemTimeAsFileTime before you start your search).

And that while FILETIME is in units of 100nsecs, the system doesn't stored the time that accurately.

Also note that you need to use FindClose() to close a find handle, not CloseHandle().

Andy

[1] If you do use GetFileTime, you need to call it like

FILEFIME ft = {0}; // a zeroed FILETIME
GetFileTime(&ft);
Last edited on
Thank you, I'm getting closer and closer. I just can't seem to place where or how to find a file that is less than one minute old...here is where I am now.......Thank you.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
struct file_data 
{ 
    std::wstring sLastAccessTime; 
    __int64 nFileSize      ; 
}; 
 
int GetFileList(const wchar_t *searchkey, std::map<std::wstring, file_data> &map) 
{ 
    WIN32_FIND_DATA fd; 
    HANDLE h = FindFirstFile(searchkey,&fd); 
    if(h == INVALID_HANDLE_VALUE) 
    { 
        return 0; // no files found 
    } 
    while(1) 
    { 
        wchar_t buf[128]; 
        FILETIME ft = fd.ftLastWriteTime; 
        SYSTEMTIME sysTime; 
        FileTimeToSystemTime(&ft, &sysTime); 
        wsprintf(buf, L"%d-%02d-%02d",sysTime.wYear, sysTime.wMonth, sysTime.wDay); 
 
        file_data filedata; 
        filedata.sLastAccessTime= buf; 
        filedata.nFileSize      = (((__int64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; 
 
        map[fd.cFileName]= filedata; 
 
        if (FindNextFile(h, &fd) == FALSE) 
            break; 
    } 
    return map.size(); 
} 
 
int main() 
{ 
    std::map<std::wstring, file_data> map; 
    GetFileList(L"C:\\Users\\DS\\Downloads\\*.jpg", map); 
    GetFileList(L"C:\\Users\\DS\\Downloads\\*.txt", map); 
	int count = GetFileList(L"C:\\Users\\DS\\Downloads\\*.pdf", map);

    for(std::map<std::wstring, file_data>::const_iterator it = map.begin(); 
        it != map.end(); ++it) 
    { 
Your code looks like it's displaying the date rather than the time. Why?

Now you're getting the ftLastWriteTime, all you have to do is compare that with the current time, so see if the difference is less that one minute.
trying to subtract time values can be quite tricky and tedious using the int-time or a time struct like SYSTIME.

I personally like using COleDateTime. This class stores its time internally as a double value.
Consequently the DATE type is a double.

We can convert from COleDateTime to DATE as follows:

COleDateTime oleDtNow = COleDateTime ::GetCurrentTime();
DATE dtNow = (DATE)oleDtNow;

dtNow stores the number of days from a particular reference in the whole number portion while the time is stored in the fraction portion.

The fraction is actually the percentage of seconds in total of the total number of seconds in a day.

Thus if we define the following:

1
2
3
const double   _1sec    =  1.0 / 86400.0;
const double   _1min    =  60 * __1sec;
const double   _1hour  =  60 * __1min;


Now if we wanted to subtract to times and test if value is less than 20 seconds we can do the following:

1
2
3
4
5
6
7
DATE dtFileTime = ...;
DATE dtNow = (DATE)COleDateTime::GetCurrentTime();

if (dtNow - dtFileTime < 20 * _1sec)
{
   //remove file
}


or you can also simply change the duration as follows:

1
2
3
4
if (dtNow - dtFileTime < 3* _1min + 20 * _1sec)
{
   //remove file
}


The COleDateTime class has a number of constructors that will allow you to convert the file time to it.

One of the constructors you may use is:

COleDateTime oleDtFile(sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);

Last edited on
Topic archived. No new replies allowed.