⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csvfileloader.cpp

📁 最新官方例子,图形,描述副,基本控件,通讯协议,等等,
💻 CPP
字号:
/**
*
* @brief Class to load a list of elements from a comma separated value (csv file
*
* Copyright (c) EMCC Software Ltd 2003
* @version 1.0
*/

// INCLUDE FILES

// Class include
#include "csvfileloader.h"

// User includes
#include "csvfileloaderobserver.h"
#include "elementlist.h"

// ================= MEMBER FUNCTIONS =======================

_LIT8(KTxtLineDelimiter, "\n");	// To delimit lines within the CSV file--might not necessarily be just \n!

CCsvFileLoader::CCsvFileLoader(RFs& aFs, CElementList& aElementList, MCsvFileLoaderObserver& aObserver)
 :	CActive(EPriorityStandard),
	iFs(aFs),
	iElementList(aElementList),
	iObserver(aObserver)
	{
	}

CCsvFileLoader::~CCsvFileLoader()
	{
	Cancel();			// All AOs should cancel when they are deleted
	iFile.Close();
	iTimeWaster.Close();
	}

void CCsvFileLoader::ConstructL(const TDesC& aFileName)
	{
	iFileName = aFileName;
	User::LeaveIfError(iFile.Open(iFs, iFileName, EFileRead));
	User::LeaveIfError(iTimeWaster.CreateLocal());
	CActiveScheduler::Add(this);	// Not done automatically!
	}

CCsvFileLoader* CCsvFileLoader::NewLC(RFs& aFs, CElementList& aElementList, MCsvFileLoaderObserver& aObserver,
	const TDesC& aFileName)
	{
	CCsvFileLoader* self = new (ELeave) CCsvFileLoader(aFs, aElementList, aObserver);
	CleanupStack::PushL(self);
	self->ConstructL(aFileName);
	return self;
	}

CCsvFileLoader* CCsvFileLoader::NewL(RFs& aFs, CElementList& aElementList, MCsvFileLoaderObserver& aObserver,
	const TDesC& aFileName)
	{
	CCsvFileLoader* self = CCsvFileLoader::NewLC(aFs, aElementList, aObserver, aFileName);
	CleanupStack::Pop(self);
	return self;
	}

void CCsvFileLoader::DoCancel()
	{
	if (iWastingTime || !iHaveTriedToLoad)
		{
		iTimeWaster.Cancel();
		}
	//Cannot cancel a file read!
	}

void CCsvFileLoader::Start()
	{
	iFilePos = 0;					//Just in case this isn't the first time round!
	iHaveTriedToLoad = EFalse;		//I want to start with a random wait first rather than a load (for the purposes of
									//this example). Hence I need a way of telling RunL() that the reason there's nothing
									//in the buffer first time round is that we haven't tried to load anything yet!

	//Wait for a randomish amount of time before doing anything else
	TInt delay = (iFileName.Size() % 10) * 100000;	//"random" enough!
	iTimeWaster.After(iStatus, delay);
	SetActive();
	}

void CCsvFileLoader::FillReadBufferL()
	{
	iHaveTriedToLoad = ETrue;			// Only check readbuffer size in RunL() if we've tried loading before!
	// Seek to current file position. We're not bothered if this is past the EOF, 
	// in that case Read() returns a zero-sized descriptor via iReadBuffer(), tested in RunL().
	User::LeaveIfError(iFile.Seek(ESeekStart, iFilePos));
										
	//R ead from the file into the buffer. iStatus will be completed by the fileserver once done.
	iFile.Read(iReadBuffer, iReadBuffer.MaxSize(), iStatus);
	
	SetActive();
	}

TPtrC8 CCsvFileLoader::ExtractToNewLineL(const TDesC8& aBuffer) const
	{
	//Search for the line delimiter within the buffer
	TInt foundPos = aBuffer.Find(KTxtLineDelimiter);
	if (foundPos < 0)
		{
		//End of line not found--malformed csv file?
		User::Leave(KErrGeneral);
		}

	//return an immutable pointer descriptor to the leftmost portion up to the delimiter location
	return aBuffer.Left(foundPos);
	}

void CCsvFileLoader::RunL()
//RunL is called on completion of the iStatus member, i.e. when the asynchronous request has finished
//(whether successfully or not)
	{
	if (!iHaveTriedToLoad)
		{
		//Fill the read buffer if we haven't yet tried to do so...
		FillReadBufferL();
		return;
		}

	if ((iStatus.Int() != KErrNone) || (iReadBuffer.Size() == 0))
		{
		//An error has occurred, or the buffer contained no data hence reading is complete. In either case,
		//return the error code (which will be KErrNone if reading has completed) to the observer.
		iObserver.NotifyLoadCompleted(iStatus.Int(), *this);
		return;
		}
	
	//This code is added simply to demonstrate the asynchronous behaviour more clearly, since without it
	//the file loading will happen so quickly that no other active object of the same or lower priority
	//than this is ever likely to get a look in...
	//Comment it out if you like. If so, you'll notice that the first instance of this class added to the
	//scheduler will "hog" it, executing every time around the scheduler's wait loop until it is fully
	//complete. Pausing a random amount of time allows other active objects to have a look in whilst this
	//instance awaits completion of the timer.
	if (iWastingTime)
		{
		//Just wait a randomish amount of time
		TInt delay = (iFilePos % 10) * 100000;
		iTimeWaster.After(iStatus, delay);
		SetActive();
		iWastingTime = EFalse;	//Don't waste time next time around!
		return;
		}

	//Extract and convert the buffer
	TPtrC8 elementBuf8 = ExtractToNewLineL(iReadBuffer);
	HBufC* elementBuf16 = HBufC::NewLC(elementBuf8.Length());	//elementBuf16 left on cleanup stack
	TPtr elementPtr16 = elementBuf16->Des();
	elementPtr16.Copy(elementBuf8);		//Copy the 8 bit buffer to the 16 bit buffer, with alternate zero padding
										//(i.e. convert from ASCII to UNICODE!)
	//Read the element from the buffer
	iElementList.AppendL(*elementBuf16);	//(could equally well have used elementPtr16)

	//Report the element that's just been loaded to the observer 
	TInt lastElementLoadedIndex = iElementList.NumberOfElements() - 1;	//-1 since zero based index!
	iObserver.NotifyElementLoaded(lastElementLoadedIndex);

	//Increment the file position
	iFilePos += elementBuf16->Length() + KTxtLineDelimiter().Length();	//Start next read from after the newline
																		//NB the use of overloaded () operator
																		//to cast a TLitC to a TDesC

	//Re-issue the request
	FillReadBufferL();

	//Cleanup
	CleanupStack::PopAndDestroy(elementBuf16);

	//Waste some time next time round before processing the file input (see comment earlier)...
	iWastingTime = ETrue;	
	}

TInt CCsvFileLoader::RunError(TInt aError)
//This function is called if a leave occurs during RunL(). aError is the leave code. If the leave is
//unhandled, then RunError() should return the leavecode for handling by the active scheduler,
//otherwise it must return KErrNone
	{
	//Notify the observer of the error
	iObserver.NotifyLoadCompleted(aError, *this);

	return KErrNone;	//KErrNone indicates we have dealt with the error so the scheduler won't panic 
	}
// End of File

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -