Join Now
Quality Rating:
  • Currently 0.0 / 5
(0.0 / 5 - 0 votes cast)
Expertise Level:
  • Currently 0.0 / 5
(0.0 / 5 - 0 votes cast)

This page was last modified 16:01, 16 March 2008.

Directory Monitoring

From Forum Nokia Wiki

This code is to monitor for file changes (added, erased) in a particular directory.

ID   Creation date March 12, 2008
Platform S60 3rd Edition S60 3rd Edition, FP1 Tested on devices N73
Category Symbian C++ Subcategory File/Data


Keywords (APIs, classes, methods, functions):


Contents

Overview

This code shows how to monitor for file changes (added/erased) in a particular directory. There is also an application showing how to use the code Source Code

This snippet can be self-signed.

MMP file (optional)

The following capabilities and libraries are required:

CAPABILITY ReadUserData


Header file

/*
 ============================================================================
 Name		: DirectoryMonitor.h
 Author	  : Olympio Cipriano
 Version	 : 1.0
 Copyright   : 
 Description : CDirectoryMonitor declaration
 ============================================================================
 */
 
#ifndef CDirectoryMonitor_H
#define CDirectoryMonitor_H
 
#include <e32base.h>	// For CActive, link against: euser.lib
#include <e32std.h>		// For RTimer, link against: euser.lib
#include <f32file.h>
 
enum TFileAction
	{
	EFileErased,
	EFileAdded
	};
 
class DirectoryObserver 
{
public:
      virtual void DirectoryChanged( const TDesC& aFileName, TFileAction aAction ) = 0;
};
 
class CDirectoryMonitor : public CActive
	{
public:
	// Cancel and destroy
	~CDirectoryMonitor();
	
	// Two-phased constructor.
	static CDirectoryMonitor* NewL( DirectoryObserver * iObserver );
	
	// Two-phased constructor.
	static CDirectoryMonitor* NewLC(DirectoryObserver * iObserver );
	
	
public:
	
	// New functions
	// Function for making the initial request
	void Monitor( const TDesC& aDirPath );
 
private:
	// C++ constructor
	CDirectoryMonitor( DirectoryObserver* aObserver );
 
	// Second-phase constructor
	void ConstructL();
	
	//directory internals
	void ListFiles( CDir*& aDir );
	
	void DiffDirectoryContents( );
	
	bool SearchEntry( const TEntry& aEntry, CDir* aDir );
	
	void Clean();
 
private:
	// From CActive
	// Handle completion
	void RunL();
 
	// How to cancel me
	void DoCancel();
 
	// Override to handle leaves from RunL(). Default implementation causes
	// the active scheduler to panic.
	TInt RunError(TInt aError);	
	
	struct TFileChange
	{
		TFileChange(const TEntry aEntry, TFileAction aAction)
		            :fileEntry(aEntry),action(aAction){}
		const TEntry fileEntry;
		TFileAction action;
	};
 
private:
	enum TCDirectoryMonitorState
		{
		EUninitialized, // Uninitialized
		EInitialized, // Initalized
		EError // Error condition
		};
 
private:
	TInt iState; // State of the active object
	RFs iFs;
	DirectoryObserver* iObserver;
	CDir* iOldDir;
	CDir* iNewDir;
	RArray<TFileChange> iFileChangeArray;
	RArray<TEntry> iFileList;
	HBufC* iPath;
	};
 
#endif // CDirectoryMonitor_H


Source file

/*
 ============================================================================
 Name		: DirectoryMonitor.cpp
 Author	  : Olympio Cipriano
 Version	 : 1.0
 Copyright   : 
 Description : CDirectoryMonitor implementation
 ============================================================================
 */
 
#include "DirectoryMonitor.h"
 
CDirectoryMonitor::CDirectoryMonitor( DirectoryObserver* aObserver ) :
	CActive(EPriorityStandard), 
	iObserver( aObserver )
	{
	}
 
CDirectoryMonitor* CDirectoryMonitor::NewLC( DirectoryObserver* aObserver )
	{
	CDirectoryMonitor* self = new ( ELeave ) CDirectoryMonitor( aObserver );
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}
 
CDirectoryMonitor* CDirectoryMonitor::NewL( DirectoryObserver* aObserver )
	{
	CDirectoryMonitor* self = CDirectoryMonitor::NewLC( aObserver );
	CleanupStack::Pop(); // self;
	return self;
	}
 
void CDirectoryMonitor::ConstructL()
	{
	User::LeaveIfError( iFs.Connect() );	
	CActiveScheduler::Add( this ); // Add to scheduler
	iPath = HBufC16::NewL(100);
	}
 
CDirectoryMonitor::~CDirectoryMonitor()
	{
	Cancel(); // Cancel any request, if outstanding
	iFs.Close();
	iFileChangeArray.Close();
	if( iOldDir )
		delete iOldDir;
	if( iNewDir )
		delete iNewDir;
	if( iPath )
		delete iPath;
	}
 
void CDirectoryMonitor::DoCancel()
	{
    iFs.NotifyChangeCancel( iStatus );
	}
 
void CDirectoryMonitor::Monitor( const TDesC& aDirPath )
	{
	*iPath = aDirPath;
	Cancel(); // Cancel any request, just to be sure
	iState = EUninitialized;
	iFs.NotifyChange( ENotifyFile, iStatus, *iPath );
	ListFiles( iOldDir );
	SetActive(); // Tell scheduler a request is active
	}
 
void CDirectoryMonitor::RunL()
{
	TInt err = iStatus.Int();  
	if ( err == KErrNone )
	{
		ListFiles( iNewDir );
		DiffDirectoryContents( );
		if( iObserver )
			for (int i = 0; i < iFileChangeArray.Count(); ++i)
			{
				TFileChange changeEntry = iFileChangeArray[i];			
				iObserver->DirectoryChanged( changeEntry.fileEntry.iName, changeEntry.action );
			}		
		Clean();
		iFs.NotifyChange( ENotifyEntry, iStatus, *iPath );
		SetActive(); // Tell scheduler a request is active 	
	}
}
 
TInt CDirectoryMonitor::RunError(TInt aError)
	{
	return aError;
	}
 
void CDirectoryMonitor::ListFiles( CDir*& aDir )
{
	if( aDir )
	{
		delete aDir;
		aDir = 0;
	}
	TInt err = iFs.GetDir( *iPath, KEntryAttNormal, ESortByName, aDir );
	if( err )
	{
	//TODO: error handling
	}
 
}
 
void CDirectoryMonitor::DiffDirectoryContents( )
{
	for (int i = 0; (iOldDir != NULL) && (i < iNewDir->Count()); ++i)
	{
		const TEntry entry = (const TEntry& )(*iNewDir)[i];
		if( ! SearchEntry( entry, iOldDir ) )
		{			
			//file added
			TFileChange change(entry,EFileAdded);
			iFileChangeArray.Append( change );
		}		
	}
	for (int i = 0; ( iOldDir != NULL ) && ( i < iOldDir->Count() ); ++i)
	{
		const TEntry entry = (const TEntry& )(*iOldDir)[i];
		if( ! SearchEntry( entry, iNewDir ) )
		{
			//file added
			TFileChange change(entry,EFileErased);
			iFileChangeArray.Append( change );
		}		
	}	
}
 
bool CDirectoryMonitor::SearchEntry( const TEntry& aEntry, CDir * aDir )
{	
	for (int i = 0; ( aDir != NULL ) && ( i < aDir->Count() ); ++i)
	{
		const TEntry& dirEntry = (const TEntry& ) (*aDir)[i];
		TDesC& entryName = (TDesC&) dirEntry.iName;
		if ( entryName.Compare( aEntry.iName ) == 0 )
			return true;				
	}
	return false;
}
 
void CDirectoryMonitor::Clean()
{
	if( iNewDir )
		{
		delete iNewDir;
		iNewDir = 0;
		}	
	iFileChangeArray.Reset();	
	ListFiles( iOldDir );
}
//end line


Postconditions

This code monitors a specific folder. A call to Monitor member funcion starts the monitoring process. The changes to be monitored are those occurred after the call to Monitor function.


Test application and other attachments

Directory Monitor Source Code: Image:DirectoryMonitoring.zip

Related Discussions
Thread Thread Starter Forum Replies Last Post
how to pass specific gcc options urrg Symbian Tools & SDKs 3 2004-07-02 08:04
Install JRE on 7610 mobiletask Mobile Java General 4 2004-10-21 08:38
Project offer - 1 euro (was: 2 Programs @ the same time) marsiboy123 General Symbian C++ 149 2008-06-19 20:12
Carbide.c++ 1.3 build error EPOC variable doesn't show to the existing directory. ashmodeus Symbian Tools & SDKs 4 2008-04-09 20:15
Detecting battery level with Javaphone API cassioli Mobile Java General 17 2007-03-19 20:16
 
Powered by MediaWiki
     
     RDF Facets:
     
     
     qfnZtopicQUqfnTopicZseriesE5f60Q
     qfnZtypeQUqfnTypeZCommunityContentQ
     qfnZtypeQUqfnTypeZWebpageQ
     qfnZtypeQUqfnTypeZWikiContentQ
     qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX