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

📄 encoder.cpp

📁 Implementation for the Huffman Cod in Visual C++. Both, the encoder and the decoder take as input
💻 CPP
字号:
#pragma warning (disable: 4996) 

#include "Encoder.h"

#include <math.h>

using namespace std;


Encoder::Encoder(LPCWSTR inputFile, LPCWSTR outputFile)
{
	//********************************************************************
	/*if( _sopen_s(&m_inputFile,inputFile,_O_RDONLY,_SH_DENYNO,_S_IREAD) != 0)
	{
		cout << "Fisierul nu a putut fi deschis" << endl;
		perror("Motiv: ");
		exit(-1);
	}
	perror("Motiv");

		
	if( _sopen_s(&m_outputFile,outputFile,_O_CREAT,_SH_DENYNO,_S_IWRITE | _S_IREAD) != 0)
	{
		cout << "Fisierul de iesire nu a putut fi creat" << endl;
		perror("Motiv: ");
		exit(-1);
	}

	perror("Motiv");*/
	//********************************************************************
	
	// Deschide fisierele.
	m_inputFile = CreateFileW((LPCWSTR)inputFile    // file to open
								   , GENERIC_READ          // open for reading
								   , FILE_SHARE_READ       // share for reading
								   , NULL                  // default security
								   , OPEN_EXISTING         // existing file only
								   , FILE_ATTRIBUTE_NORMAL // normal file
								   , NULL
								   );
	
	if(m_inputFile == INVALID_HANDLE_VALUE)
	{
		cout << "Fisierul de intrare nu a putut fi deschis" << endl;
		exit(-1);
	}
	
	m_outputFile = CreateFileW((LPCWSTR)outputFile    // file to create
								   , GENERIC_WRITE          // open for writing
								   , FILE_SHARE_READ       // share for reading
								   , NULL                  // default security
								   , CREATE_ALWAYS         // existing file only
								   , FILE_ATTRIBUTE_NORMAL // normal file
								   , NULL
								   );
	if(m_outputFile == INVALID_HANDLE_VALUE)
	{
		// Inchide handleul fisierul de input.
		CloseHandle(m_inputFile);
		cout << "Fisierul de iesire nu a putut fi deschis" << endl;
		exit(-1);
	}

	m_contorBuffer = 0;

}

Encoder::~Encoder(void)
{
	/*_close(m_inputFile);
	_close(m_outputFile);*/

	CloseHandle(m_inputFile);
	CloseHandle(m_outputFile);
}

void Encoder::Encode()
{
	SYMBOL_TYPE symbol;		// simbolul curent
	DWORD bytesRead;		// numarul de bytes cititi
	DWORD bytesWritten;		// numarul de bytes scrisi
	bool isLeaf;			// retine daca simbolul se afla printre frunze
	

	//citesc primul caracter
	//if((bytesRead = _read(m_inputFile,&symbol,sizeof(SYMBOL_TYPE))) > 0)
	if(ReadFile(m_inputFile, (LPVOID)&symbol, sizeof(symbol), &bytesRead, NULL) && bytesRead > 0)
	{
		//_write(m_outputFile,&symbol,bytesRead);
		WriteFile(m_outputFile, (LPCVOID)&symbol, sizeof(symbol), &bytesWritten, NULL);
		m_tree.Insert(symbol);
		m_tree.Sibling();
	}
	else
	{
		cout << "Nu s-a putut citi din fisier sau fiserul este gol" << endl;
		exit(-1);
	}

	// citesc restul caracterelor
	//while((bytesRead = _read(m_inputFile,&symbol,sizeof(SYMBOL_TYPE))) > 0)
	while(ReadFile(m_inputFile, (LPVOID)&symbol, sizeof(symbol), &bytesRead, NULL) && bytesRead > 0) 
	{
		isLeaf = false;
		for(unsigned int i = 0; i < m_tree.nrLeaves; i++)
		{
			// Daca se afla in arbore scriu codul curent
			if(m_tree.m_leaves[i]->symbol == symbol)
			{
				isLeaf = true;
				WriteToBuffer(i);
				m_tree.Insert(symbol);
				m_tree.Sibling();
				
				break;
			}
		}
		
		// daca nu se afla in arboare scriu intai codul "esc"
		if(!isLeaf)
		{
			WriteToBuffer((unsigned int)0);
			m_tree.Insert(symbol);
			m_tree.Sibling();
			WriteToBuffer((SYMBOL_TYPE)symbol);	
		}
					
	}
	// La sfarsit mai adaug codul "esc" pentru a evita
	// confuziile in caz de neumplere a bufferului
	if(m_contorBuffer > 0)
	{
		WriteToBuffer((unsigned int)0);
		// dupa codul "esc" adaug 0 pt ca noul caracter sa fie vid
		if(m_contorBuffer != 0)
		{
			for(int i = m_contorBuffer; i < SYMBOL_SIZE; i++)
				m_buffer[i] = 0;
			WriteBufferToFile();
		}
	}
}

// Write the codification of the leaf in buffer
// When buffer become full it's written to file
void Encoder::WriteToBuffer(unsigned int leafNumber)
{
	static bool bufferAux[SYMBOL_NUMBER]; // retine drumul frunze-> radacina
	int contorBufferAux = 0;
	NOD_HUFFMAN *pAux = m_tree.m_leaves[leafNumber]->pParrent;

	if(pAux->pLeftChild == m_tree.m_leaves[leafNumber])
		bufferAux[contorBufferAux++] = 0;
	else
		bufferAux[contorBufferAux++] = 1;
	
	while((pAux != NULL) && (pAux != m_tree.m_pRoot))
	{
		if(pAux->pParrent->pLeftChild == pAux)
			bufferAux[contorBufferAux++] = 0;
		else
			bufferAux[contorBufferAux++] = 1;
		pAux = pAux->pParrent;
	}
	
	// scriu in buffer codul corect( inversul din bufferAux)
	for(int i = (contorBufferAux - 1); i >= 0; i--)
	{
		m_buffer[m_contorBuffer++] = bufferAux[i];
		if(m_contorBuffer == SYMBOL_SIZE)
		{
			WriteBufferToFile();
			m_contorBuffer = 0;
		}
	}
}

// Write the codification of the leaf in buffer
// When buffer become full it's written to file
void Encoder::WriteToBuffer(SYMBOL_TYPE symbol)
{
	unsigned int aux;
	for(int i = (SYMBOL_SIZE - 1); i >= 0; i--)
	{
		aux = 1 << i;
		m_buffer[m_contorBuffer++] = (((symbol & aux) == aux) ? 1 : 0);
		
		if(m_contorBuffer == SYMBOL_SIZE)
		{
			WriteBufferToFile();
			m_contorBuffer = 0;
		}
	}
}

// Write the buffer to file
void Encoder::WriteBufferToFile()
{
	unsigned int aux = 0;
	SYMBOL_TYPE symbol;
	DWORD bytesWritten;

	//static SYMBOL_TYPE fileBuffer[2000];
	//static int fileBufferContor = 0;

	// Creez intai simbolul ce va fi scris
	for(int i = (SYMBOL_SIZE - 1); i >= 0 ; i--)
	{
		if(m_buffer[i])
			aux += (1 << (SYMBOL_SIZE - 1 - i));
	}
	symbol = aux;
//	fileBuffer[fileBufferContor++] = symbol;

	//if (fileBufferContor == 1999)
	//{

		//_write(m_outputFile,&symbol,SYMBOL_SIZE);
		WriteFile(m_outputFile, (LPCVOID)&symbol, sizeof(symbol), &bytesWritten, NULL);
	//}
}

⌨️ 快捷键说明

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