Xedi.Xermawan's Blog

personal-technical blog

File mana yang termodifikasi ?

leave a comment »

Misalnya saya memiliki 1000 file yang akan saya prosess oleh suatu program, dengan script saya bisa melakukannya seperti ini :

for i=0 to i=1000 { process file ke-i }      

jadi dengan klik sebuat script pekerjaan selesai. Namun, ada beberapa file dari 1000 file tersebut yang berubah / saya modifikasi lagi, sehingga saya perlu mengulang eksekusi script diatas lagi :

for i=0 to i=1000 { process file ke-i }      

Ini tentu tidak efisien dan lama, karena saya mengubah beberapa file, namun 1000 file masih diprocess lagi. Kode yang efisien seharusnya begini :

for i=0 to i=1000 { jika file ke-i ter-modifikasi, maka process file ke-i }    

untuk itu saya perlu suatu program untuk mengecek apakah file ke-i, termodifikasi / tidak. Pekerjaan semacam ini bisa mungkin saja dilakukan dengan python, lua, atau scripting language yang lain. Namun kali ini , (dan waktu2yg lain) , saya suka pakai c/c++ dengan kombinasi Batch , hehehe. Dan, program super simple itu sudah jadi, xediff.exe :d . berikut contoh efisien script yang saya maksud .

[ run_works.bat ]

@echo off
SET XDIFF=N:\XediProjects\Release\Xediff.exe
SET TARGETDIR=D:\test\test
for %%i in ( %TARGETDIR%\*.* ) do (
 call checkmodified.bat %%i
)
echo .. Done..

[ checkmodified.bat ]

@echo off
%XDIFF% %1 > temp.txt
set /p XDF= < temp.txt
 if "%XDF%"=="1" (
 @echo ..do something: this file changed %1 %XDF%
 )
del temp.txt

Terdapat 2 file batch, run_works.bat yang memanggil checkmodified.bat. Alasan kenapa jadi 2 file BAT adalah : pipe di BAT tidak bisa bekerja. { apa itu pipe? } . lalu apa yang dilakukan xediff.exe? : xediff.exe menerima argumen berupa file path , dan memberikan output (stdout) ‘1’ & ‘0’  ,file termodifikasi atau tidak . xediff.exe adalah program simple yang mengecek last written time dari suatu file . berikut kodenya [ this is ugly, but i like to share 🙂    ]

[xediff.exe]

// Xedi Xermawan <c> 2013
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <fstream>

using namespace std;

bool GetLastWriteTime(HANDLE hFile, SYSTEMTIME& lastaccess,TCHAR* fileLastAccess)	{
	bool isEqual = true;
    FILETIME ftCreate, ftAccess, ftWrite;
    SYSTEMTIME stUTC, stLocal;
    // Retrieve the file times for the file.
    if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))
        return false;
    // Convert the last-write time to local time.
    FileTimeToSystemTime(&ftWrite, &stUTC);
    SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
	if(stLocal.wMonth != lastaccess.wMonth ||
	   stLocal.wDay!= lastaccess.wDay ||
	   stLocal.wYear!= lastaccess.wYear ||
       stLocal.wHour!= lastaccess.wHour ||
	   stLocal.wMinute!= lastaccess.wMinute ||
	   stLocal.wSecond!= lastaccess.wSecond
	   )
	{
		isEqual = false;
	}
	fstream fileOut(fileLastAccess,std::ios::out|std::ios::binary);
	const char* c=reinterpret_cast<const char*>(&stLocal);
	fileOut.write(c,sizeof(stLocal));
	fileOut.close();
	return isEqual;
}

bool GetLastTimeAccess(SYSTEMTIME& ret, TCHAR* fileLastAccess)  {
	fstream fileIn(fileLastAccess,std::ios::in | std::ios::binary);
	if(!fileIn) {
		return false;
	}
	fileIn.read( reinterpret_cast<char*>(&ret), sizeof(ret) );
	fileIn.close();
	return true;
}

void BreakPath(TCHAR* filepath, TCHAR* filedir, TCHAR* filename)	{
	unsigned int i=0,lastSlash=0;
	TCHAR buff[MAX_PATH];
	while(*filepath !='')	{
		buff[i] = *filepath;
		if(*filepath++=='\\')
			lastSlash=i;
		i++;
	}
	buff[i]='\0';
	i=0;
	while(i < lastSlash+1)	{
		*filedir++ = buff[i++];
	}
	*filedir++ ='.';
	*filedir++ ='x';
	*filedir++ ='d';
	*filedir++ ='f';
	*filedir++ ='\\';
	*filedir='';
	while(buff[i] !='')	{
		*filename++ = buff[i++];
	}
	*filename ='\0';
}

void FixPath(TCHAR* filedir, TCHAR* filename,TCHAR* filenamefix)	{
	while(*filedir !='')	{
		*filenamefix++ = *filedir++;
	}
	while(*filename !='')	{
		*filenamefix++ = *filename++;
	}
	*filenamefix++='.';
	*filenamefix++='x';
	*filenamefix++='d';
	*filenamefix++='i';
	*filenamefix++='f';
	*filenamefix++='f';
	*filenamefix='\0';
}

int _tmain(int argc, TCHAR *argv[])	 {
    HANDLE hFile;
	int retVal = 1;
    if( argc != 2 )	{
        retVal = 1;
		printf("%d",retVal);
		return retVal;
    }
	TCHAR* filepath = argv[1];
	TCHAR filedir[MAX_PATH];
	TCHAR filename[MAX_PATH];
	TCHAR filename_fix[MAX_PATH];
	SYSTEMTIME lastaccessnoted;
	BreakPath(filepath,filedir,filename);
	CreateDirectory( filedir , NULL );
	FixPath(filedir,filename,filename_fix);
	GetLastTimeAccess(lastaccessnoted, filename_fix );
    hFile = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL,OPEN_EXISTING, 0, NULL);

    if(hFile == INVALID_HANDLE_VALUE)	{
        retVal = 1;
		printf("%d",retVal);
		return retVal;;
    }
    if( (GetLastWriteTime( hFile, lastaccessnoted, filename_fix ) ))	 {
		retVal = 0;	// file same // not modified
		printf("%d",retVal);
		return retVal;;
	}
    CloseHandle(hFile);
	printf("%d",retVal);
	return retVal;
}

// edi ermawan // yogjakarta 27042013

// keywords: file modified  check, c++, c, Batch, incremental build

Written by XediXermawan

April 26, 2013 at 6:07 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: