www.pudn.com > matlab7.x.rar > matfile.cpp


 
#include "matfile.h" 
#include  
#include  
 
CMatFile::CMatFile() 
{ 
	needByteSwap = false;	 
	dataMap.clear(); 
	dataNames.clear(); 
} 
 
CMatFile::CMatFile(std::string const& matfile) 
{ 
	dataMap.clear(); 
	dataNames.clear(); 
	ReadFile(matfile); 
} 
 
CMatFile::~CMatFile() 
{ 
	dataMap.clear(); 
	dataNames.clear(); 
} 
 
 
void CMatFile::ReadFile(std::string const& matfile) 
{ 
	std::ifstream inFile; 
	inFile.open(matfile.c_str(), std::ios_base::binary); 
	if ( !inFile.good() ) 
	{ 
		return ; 
	} 
	long fileLength, filePos; 
	inFile.seekg(0, std::ios::end); 
	fileLength = inFile.tellg(); 
	//std::cout << "File size is " << fileLength << std::endl; 
	inFile.seekg(0, std::ios::beg); 
	inFile.read(reinterpret_cast(&matHeader),  
			 	sizeof(matHeader) ); 
	short endian1 = 0x4d49; // "MI" means no need to swap bytes 
	short endian2 = 0x494d; // "IM" means need swap bytes 
	 
	if ( matHeader.endian == endian1 ) 
	{ 
		needByteSwap = false; 
	} 
	else if ( matHeader.endian == endian2 ) 
	{ 
		needByteSwap = true; 
	} 
	else 
	{ 
		// something must be wrong 
		inFile.close(); 
		return; 
	} 
 
	 
	//if ( !inFile.eof() ) 
	while ( !inFile.eof() ) 
	{ 
		//filePos = inFile.tellg(); 
		//std::cout << "Current position is " << filePos << std::endl; 
		// now we are at the position of the first data element  
		ElementTag tagTemp; 
		inFile.read(reinterpret_cast(&tagTemp), sizeof(ElementTag) ); 
		if (inFile.eof() ) 
		{ 
			break; 
		} 
		 
		if ( tagTemp.dataType == 14 ) // miMATRIX 
		{ 
			ParseMatlabArray(inFile, tagTemp.numBytes); 
		} 
		else 
		{ 
			// currently not implemented, just skip 
			inFile.seekg(tagTemp.numBytes, std::ios_base::cur); 
		} 
 
		// to makesure the next data tag is 16-byte aligned 
/* 
 		long offset; 
		filePos = inFile.tellg(); 
 
		if ( filePos % 16 != 0 ) 
		{ 
			offset = 16- filePos % 16; 
			inFile.seekg(offset, std::ios_base::cur); 
		}			 
*/	 
	} 
	 
	inFile.close(); 
	 
} 
 
void CMatFile::PrintHeader() 
{ 
	std::cout << "Header text:" << std::endl; 
	std::cout << matHeader.info << std::endl; 
	std::cout << "version = " << matHeader.version 
				<< std::endl; 
	//char* pEndian = reinterpret_cast (&matHeader.endian); 
	char* pEndian = (char*) (&matHeader.endian); 
	char endian[3] = {0}; 
	 
	// because we are testing on windows, which is little endian 
	endian[0] = pEndian[1]; 
	endian[1] = pEndian[0]; 
	std::cout << "endian = " << endian 
			<(&arrayFlags),  
					sizeof(ElementTag)); 
	 
	readSize += sizeof(ElementTag); 
	 
	unsigned int flags[2]; 
	inFile.read(reinterpret_cast(&flags[0]), 8); 
/*	 
	// test for complex data 
	if ( flags[0] & 0x0800 ) 
	{ 
		std::cout << "Data is complex" << std::endl; 
	} 
	else 
	{ 
		std::cout << "Data is real" << std::endl; 
	} 
		 
	// test for global data 
	if (flags[0] & 0x0400) 
	{ 
		std::cout << "Data is global" << std::endl; 
	} 
	else 
	{ 
		std::cout << "Data is not a global" << std::endl; 
	} 
		 
	// test for logical 
	if ( flags[0] & 0x0100) 
	{ 
		std::cout <<"Data is logical" << std::endl; 
	} 
	else 
	{ 
		std::cout << "Data is not logical" < (&dimensions),  
				sizeof(ElementTag) ); 
	readSize += sizeof(ElementTag); 
	unsigned int numDimensions = dimensions.numBytes/4; 
	 
	int i; 
	int dim; 
	int *arrayDim; 
	arrayDim = new int [numDimensions]; 
	long total_length = 1; 
	for (i =0; i< (int)numDimensions; ++i) 
	{ 
		inFile.read(reinterpret_cast (&dim), 4); 
		arrayDim[i] = dim; 
		total_length *= dim; 
	} 
		 
	// array Name 
	std::string array_name; 
	SmallData arrayNameTag; 
	inFile.read(reinterpret_cast(&arrayNameTag), 
				sizeof(SmallData) ); 
	if ( arrayNameTag.dataType != 0 ) // array name is small 
	{ 
		array_name = arrayNameTag.data; 
	} 
	else 
	{ 
		ElementTag arrayNameTag1; 
		inFile.seekg(-8, std::ios_base::cur); 
		inFile.read(reinterpret_cast(&arrayNameTag1), 
					sizeof(ElementTag) ); 
					 
		int nameLen = arrayNameTag1.numBytes; 
		if ( nameLen % 8 != 0) 
		{ 
			nameLen += 8- nameLen%8; 
		} 
		 
		char *pName = NULL; 
		pName = new char[nameLen+1]; 
		pName[nameLen] = '\0'; 
		inFile.read(pName, nameLen); 
		array_name = pName; 
		 
		delete [] pName; 
	} 
	 
	// real part of the data 
	ElementTag realPartTag; 
	inFile.read(reinterpret_cast(&realPartTag),  
				sizeof(ElementTag) ); 
 
	// make sure array is 64-bit aligned				 
	long dataLen = realPartTag.numBytes; 
	if ( dataLen % 8 != 0 ) 
	{ 
		dataLen += 8- dataLen % 8; 
	} 
	char * data; 
	data = new char[dataLen]; 
	inFile.read(data, dataLen ); 
 
	// create a DataElement object 
	DataElement* pData = new DataElement; 
	pData->SetFlags(flags); 
	pData->SetDimension(numDimensions, arrayDim, total_length); 
	pData->SetArrayName( array_name ); 
	if ( (flags[0] & 0xff) == 6 ) // double  
	{ 
		pData->SetDoublePr(reinterpret_cast(data) ); 
		if ( pData->IsComplex() ) 
		{ 
			pData->SetDoublePi(reinterpret_cast(data)); 
		} 
	} 
	else  
	{ 
		std::cout << "Only double is supported!" << std::endl; 
		delete [] data; 
	} 
	 
	// insert the data to the map 
	dataMap.insert(std::make_pair(array_name, pData) ); 
	dataNames.push_back(array_name); 
	 
	 
	//delete [] data; 
	delete [] arrayDim; 
		 
	// to makesure the next data tag is 16-byte aligned 
/*	long filePos, offset; 
	filePos = inFile.tellg(); 
	if ( filePos % 16 != 0 ) 
	{ 
		offset = 16- filePos % 16; 
		inFile.seekg(offset, std::ios_base::cur); 
	} 
*/	 
} 
 
int CMatFile::GetDataNames(std::vector& names) 
{ 
	int retVal = -1; 
	names = dataNames; 
	 
	retVal = names.size(); 
	 
	return retVal; 
} 
 
DataElement* CMatFile::GetDataElement(std::string& name) 
{ 
	DataElement* retVal = NULL; 
	 
	std::map::iterator it; 
	 
	it = dataMap.find(name); 
	if ( it != dataMap.end() ) 
	{ 
		retVal = it->second; 
	} 
	 
	return retVal; 
}