示例#1
0
int main(){
    Node *tree;
    int codeTable[27], codeTable2[27];
    int compress;
    char filename[20];
    FILE *input, *output;

    buildHuffmanTree(&tree);

    fillTable(codeTable, tree, 0);

    invertCodes(codeTable,codeTable2);

    /*get input details from user*/
    printf("Type the name of the file to process:\n");
    scanf("%s",filename);
    printf("Type 1 to compress and 2 to decompress:\n");
    scanf("%d",&compress);

    input = fopen(filename, "r");
    output = fopen("output.txt","w");

    if (compress==1)
        compressFile(input,output,codeTable2);
    else
        decompressFile(input,output, tree);

    return 0;
}
示例#2
0
void HuffmanCodes(char data[], int freq[], int size)
{

    struct MinHeapNode* root = buildHuffmanTree(data, freq, size);
    int arr[MAX_TREE_HT], top = 0;
    printCodes(root, arr, top);
}
int main(int nargs, char * args[]) {	
	if(nargs < 2) {
		fprintf(stderr, "USAGE: %s <symbol_string>\n", args[0]);
		exit(EXIT_FAILURE); 
	}
	//symbol index is symbol char val - 'a'
	//ASSUMES chars are all lowercase
	//determine frequency of symbols
	calcFrequency(args[1]);
	printFrequency();
	
	//build the priority q for each char/frequency in frequency array
	initQueue();
	buildQueue();
	
	//priority queue is done so build the huffman tree
	root = NULL;
	buildHuffmanTree();
	if(root == NULL) {
		freeQueue();//should already be empty, but just in case
		return(EXIT_FAILURE);
	}
	
	calcCodes();
	
	if(nargs > 2) 
		printHuffmanCode(args[2]);
	else
		printHuffmanCode(args[1]);
	
	freeTree();
	return(EXIT_SUCCESS);
}
示例#4
0
// The main function that builds a Huffman Tree and print codes by traversing
// the built Huffman Tree
void HuffmanCodes(char data[], int freq[], int size)
{
   //  Construct Huffman Tree
   struct node* root = buildHuffmanTree(data, freq, size);
 
   // Print Huffman codes using the Huffman tree built above
   int arr[MAX_TREE_HT], top = 0;
   printCodes(root, arr, top);
}
示例#5
0
static struct fblock *fb_huf_ctor(char *name)
{
	int ret = 0;
	struct fblock *fb;
	struct fb_huf_priv *fb_priv;
	struct proc_dir_entry *fb_proc;
	Node *tree;
	fb = alloc_fblock(GFP_ATOMIC);
	if (!fb)
		return NULL;
	fb_priv = kzalloc(sizeof(*fb_priv), GFP_ATOMIC);
	if (!fb_priv)
		goto err;
	seqlock_init(&fb_priv->lock);
	rwlock_init(&fb_priv->klock);
	fb_priv->port[0] = IDP_UNKNOWN;
	fb_priv->port[1] = IDP_UNKNOWN;

	ret = init_fblock(fb, name, fb_priv);
	if (ret)
		goto err2;

	fb->netfb_rx = fb_huf_netrx;
	fb->event_rx = fb_huf_event;
//	fb->linearize = fb_aes_linearize;
//	fb->delinearize = fb_aes_delinearize;
	fb_proc = proc_create_data(fb->name, 0444, fblock_proc_dir,
				   &fb_huf_proc_fops, (void *)(long) fb);
	if (!fb_proc)
		goto err3;

	ret = register_fblock_namespace(fb);
	if (ret)
		goto err4;

	__module_get(THIS_MODULE);

	
	buildHuffmanTree(&tree);
	fillTable(tree, 0);
	invertCodes();


	return fb;
err4:
	remove_proc_entry(fb->name, fblock_proc_dir);
err3:
	cleanup_fblock_ctor(fb);
err2:
	kfree(fb_priv);
err:
	kfree_fblock(fb);
	return NULL;
}
示例#6
0
void encodeFile() {
	unsigned char TempChar = 0;
	readFromOriginalFile();
	initHuffmanList();
	buildHuffmanTree();
	finalExecution(0);
	if (ifOnlyOneCharacter(&TempChar)) {
		SLEncodeMap * EncodeMap = getEncodeMap();
		EncodeMap[TempChar].BitBuffer = "0";
	}
	writeToFile();
}
示例#7
0
void Archiver::compress(string& pathOfOrigin, string& pathOfArchive)
{
    map<char, int>* freqTable = buildFreqTable(pathOfOrigin);
    Node* root = buildHuffmanTree(freqTable);
    map<char, string> codeTable;
    string codeOfSymbol = "";
    buildSymbolsCodeTable(root, &codeTable, codeOfSymbol);
    string encryptedTree = "";
    getEncryptedTree(root, encryptedTree);
    string encryptedData = getEncryptedData(pathOfOrigin, &codeTable);
    writeToFile(pathOfArchive, encryptedTree, encryptedData);
    freeMemoryAfterCompression(freqTable, root);
}
示例#8
0
void decodeFile() {
	unsigned char TempChar = 0;
	readFromCompressedFile();
	initHuffmanList();
	buildHuffmanTree();
	if (ifCompressedOnlyOneCharacter(&TempChar)) {
		SLHuffmanList * Head = getHuffmanListHead();
		SLHuffmanList * NewNode = (SLHuffmanList *)malloc(sizeof(SLHuffmanList));
		NewNode->Next = NULL;
		NewNode->Character = TempChar;
		NewNode->LeftNode = NULL;
		NewNode->RightNode = NULL;
		NewNode->NodeWeight = Head->Next->NodeWeight;
		Head->Next->LeftNode = NewNode;
		Head->Next->RightNode = NewNode;
	}
	finalExecution(1);
}
void HuffmanCodes(char data[], int freq[], int size)
{
	MinHeapNode* root = buildHuffmanTree(data, freq, size);
	int arr[128], top=0;
	printCodes(root, arr, top);
}
示例#10
0
int main(int argc, char **argv){
	clock_t start, end;
	unsigned int cpu_time_used;
	unsigned int i, j;
	unsigned int distinctCharacterCount, outputFileLengthCounter, outputFileLength, combinedHuffmanNodes, frequency[256], compressedFileLength;
	unsigned char currentInputBit, currentInputByte, *compressedData, *outputData, bitSequence[255], bitSequenceLength = 0;
	FILE *compressedFile, *outputFile;
	
	// open source compressed file
	compressedFile = fopen(argv[1], "rb");
	
	// read the header and fill frequency array
	fread(&outputFileLength, sizeof(unsigned int), 1, compressedFile);
	fread(frequency, 256 * sizeof(unsigned int), 1, compressedFile);
	
	// find length of compressed file
	fseek(compressedFile, 0, SEEK_END);
	compressedFileLength = ftell(compressedFile) - 1028;
	fseek(compressedFile, 1028, SEEK_SET);
	
	// allocate required memory and read the file to memoryand then close file
	compressedData = malloc((compressedFileLength) * sizeof(unsigned char));
	fread(compressedData, sizeof(unsigned char), (compressedFileLength), compressedFile);
	fclose(compressedFile);
	
	// start time measure
	start = clock();
	
	// initialize nodes of huffman tree
	distinctCharacterCount = 0;
	for (i = 0; i < 256; i++){
		if (frequency[i] > 0){
			huffmanTreeNode[distinctCharacterCount].count = frequency[i];
			huffmanTreeNode[distinctCharacterCount].letter = i;
			huffmanTreeNode[distinctCharacterCount].left = NULL;
			huffmanTreeNode[distinctCharacterCount].right = NULL;
			distinctCharacterCount++;
		}
	}

	// build tree 
	for (i = 0; i < distinctCharacterCount - 1; i++){
		combinedHuffmanNodes = 2 * i;
		sortHuffmanTree(i, distinctCharacterCount, combinedHuffmanNodes);
		buildHuffmanTree(i, distinctCharacterCount, combinedHuffmanNodes);
	}

	// build huffmanDictionary having the bitSequence sequence and its length
	buildHuffmanDictionary(head_huffmanTreeNode, bitSequence, bitSequenceLength);

	// write the data to file
	outputData = malloc(outputFileLength * sizeof(unsigned char));
	current_huffmanTreeNode = head_huffmanTreeNode;
	outputFileLengthCounter = 0;
	for (i = 0; i < compressedFileLength; i++){
		currentInputByte = compressedData[i];
		for (j = 0; j < 8; j++){
			currentInputBit = currentInputByte & 0200;
			currentInputByte = currentInputByte << 1;
			if (currentInputBit == 0){
				current_huffmanTreeNode = current_huffmanTreeNode->left;
				if (current_huffmanTreeNode->left == NULL){
					outputData[outputFileLengthCounter] = current_huffmanTreeNode->letter;
					current_huffmanTreeNode = head_huffmanTreeNode;
					outputFileLengthCounter++;
				}
			}
			else{
				current_huffmanTreeNode = current_huffmanTreeNode->right;
				if (current_huffmanTreeNode->right == NULL){
					outputData[outputFileLengthCounter] = current_huffmanTreeNode->letter;
					current_huffmanTreeNode = head_huffmanTreeNode;
					outputFileLengthCounter++;
				}
			}
		}
	}

	//display runtime
	end = clock();
	
	// write decompressed file
	outputFile = fopen(argv[2], "wb");
	fwrite(outputData, sizeof(unsigned char), outputFileLength, outputFile);
	fclose(outputFile);
	
	cpu_time_used = ((end - start)) * 1000 / CLOCKS_PER_SEC;
	printf("Time taken: %d:%d s\n", cpu_time_used / 1000, cpu_time_used % 1000);
	free(outputData);
	free(compressedData);
	return 0;
}
bool fcomprAdaptHuffCode(const char * target, const char *source)
{
	if (!target || !source) // Один из параметров пуст
	{
		return false;
	}

	/* Открываем исходный файл на чтение */
	std::ifstream fSource; // Переменная входного потока
	std::filebuf * fSourceBuf = fSource.rdbuf(); // Устанавливаем указатель на буфер входного потока
	fSourceBuf->open(source, std::ios::in | std::ios::binary); // Открываем файл на чтение
	if (!fSourceBuf->is_open())
	{
		return false;
	}

	/* Открываем целевой файл на запись */
	std::ofstream fTarget; // Переменная выходного потока
	std::filebuf * fTargetBuf = fTarget.rdbuf(); // Устанавливаем указатель на буфер выходного потока
	fTargetBuf->open(target, std::ios::out | std::ios::binary | std::ios::trunc); // Открываем файл на запись и удаляем содержимое (если есть)
	if (!fTargetBuf->is_open())
	{
		return false;
	}

	/* Цикл сжатия целевого файла адаптивным алгоритмом Хаффмана */
	char ch; // Переменная для чтения символов из файла
	unsigned i; // Переменные-индексы
	int k;
	unsigned counts[AlphabetSize] = {0}; // Массив счетчиков символов
	std::vector <vertex *> window; // Список для хранения статистики вхождений символов в окно
	std::vector<vertex *> arrayFullData; // Переменная для хранения списка с кодами Хаффмана
	bool isStartCycle = true; // Переменная-флаг является ли данный проход начальным 
	vertex * currNode; // Переменная для хранения структуры с необходимым символом
	unsigned char pushByte = 0; // Переменная для выброса сформированного байта в поток
	unsigned char numBits = 0; // Переменная для хранения количества значимых битов в байте
	const unsigned char SeniorBit = 128; // Константа для установки старшего бита в байте
	unsigned char flag = SeniorBit; // Переменная-флаг для указания устанавливаемого бита в байте
	unsigned int total = 0; // Переменная подсчета количества сжатых символов
	unsigned char limit; /* Переменная для определения количества сжимаемых символов 
						 (в первом цикле их размер окна + 1 символ, далее по 1 символу) */

	while (true)
	{
		if (!isStartCycle) // Не начальный цикл
		{
			// Проверяем, есть ли в файле символы для кодирования
			ch = fSourceBuf->sgetc();
			if (ch == EOF)
			{
				break;
			}
			// Смещаем файловый указатель на размер окна
			fSourceBuf->pubseekoff(-WindowSize, std::ios::in);

			/* Сбрасываем счетчики символов */
			for (i = 0; i < AlphabetSize; i++)
			{
				counts[i] = 0;
			}
		}

		/* Цикл заполнения окна */
		for (i = 0; i < WindowSize; i++)
		{
			ch = fSourceBuf->sbumpc();
			if (ch == EOF) // Неожиданный конец файла
			{
				return false;
			}
		
			/* Инкрементируем счетчик в соответствующей позиции */
			if (ch == 0xA) // Символ новой строки
			{
				counts[NL]++;
			}
			else if (ch == 0xD) // Символ возврата каретки
			{
				counts[CR]++;
			}
			else if (ch <= 0x1F && ch >= 0x7F) // Пропускаем управляющие и символы расширенной таблицы
			{
				continue;
			}
			else // Печатные символы ascii таблицы
			{
				counts[ch - 0x20]++;
			}
		}

		/* Сохраняем статистику в список */
		for (i = 0; i < AlphabetSize; i++)
		{
			vertex * currNode = new vertex;
			if (i == NL) // Символ новой строки
			{
				currNode->ch = 0xA;
			}
			else if (i == CR) // Символ возврата каретки
			{
				currNode->ch = 0xD;
			}
			else // Печатные символы
			{
				currNode->ch = i + 0x20;
			}
			currNode->count = counts[i];
			currNode->left = 0;
			currNode->right = 0;
			window.push_back(currNode);
		}

		/* Формируем коды Хаффмана */
		vertex * root = buildHuffmanTree(window);

		/* Освобождаем вектор */
		for (i = 0; i < AlphabetSize; i++)
		{
			delete window[i];
		}
		window.clear();

		/* Считываем коды в массив */
		arrayFullData = readDataFromHuffmanTree(root);

		/* Освобождаем дерево */
		freeTree(root);
		root = 0;

		/* Сортируем массив в порядке расположения символов в ascii таблице */
		arrayFullData = sortByAlphabet(arrayFullData);

		if (isStartCycle) // Стартовый цикл
		{
			/* Фомируем заголовок сжатых данных. Он содержит счетчики вхождения символов,
			позиция байта счетчика однозначно определяет сам символ. */

			/* Процесс записи заголовка. Записываем только значения счетчиков, 
			положение счетчика однозначно определяет символ. Счетчики занимают первые 96 байт файла */
			for (i = 0; i < arrayFullData.size(); i++)
			{
				fTargetBuf->sputc(arrayFullData[i]->count);
			}

			/* Нужно придумать как вставить счетчик символов во входном файле.
			Он необходим для корректной распаковки */
		}
	
		/* Кодируем файл */
		if (isStartCycle)
		{
			fSourceBuf->pubseekoff(-WindowSize, std::ios::in); // Смещаем указатель в исходном файле в начальную позицию
		}

		/* Цикл считывания и кодирования символов */

		/* Определеяем количество кодируемых символов
		на старте оно равно размеру окна плюс один символ
		далее по одному символу */
		switch (isStartCycle)
		{
		case true : 
			{
				limit = WindowSize + 1;
				break;
			}
		case false :
			{
				limit = 1;
			}
		}
		for (i = 0; i < limit; i++)
		{
			ch = fSourceBuf->sbumpc();
			if (ch == EOF) // Неожиданный конец файла
			{
				return false;
			}

			/* Ищем код, соответствующий считанному символу */
			currNode = searchNodeBySym(arrayFullData, ch);
			if(!currNode) // Символ не найден
			{
				return false;
			}

			/* Формируем байт для помещения его в выходной поток */
			if (currNode->length <= ByteSize - numBits) // Длина кода меньше либо равна количеству значащих битов в выходном байте
			{
				for (k = currNode->length - 1; k >= 0; k--) // Читаем биты кода в байт
				{
					if (currNode->code[k]) // Бит установлен в единицу
					{
						pushByte |= flag; // Устанавливаем соответствующий бит в выбрасываемом байте
						flag >>= 1; // Сдвигаем флаг в младший бит
						numBits++; // Инкрементируем количество значащих битов в байте
					}
					else // Бит установлен в ноль
					{
						flag >>= 1; // Просто сдвигаем флаг в младший бит
						numBits++; // Инкрементируем количество значащих битов в байте
					}
				}
				if (numBits == ByteSize) // Байт полностью заполнен, выбрасываем в поток
				{
					fTargetBuf->sputc(pushByte);
					pushByte = 0;
					numBits = 0;
					flag = SeniorBit;
					continue;
				}
				else // Байт заполнен не полностью
				{
					continue;
				}
			}
			else // Код символа больше, чем количество значащих битов в байте
			{
				/* Считываем первую часть кода в байт */
				for (k = currNode->length - 1; numBits < ByteSize; k--)
示例#12
0
文件: main.c 项目: rarry/it
int main()
{


    char * inFp = "C:\\abc.txt";
    //char * inFpZeroes= "C:\\abc_zeroes.txt";
    char * inFpCrc = "C:\\abc_crc.txt";
    char * outFp = "C:\\abc_compressed.txt";
    char * decompressedFpCrc = "C:\\abc_decompressed_crc.txt";
    char * decompressedFp = "C:\\abc_decompressed.txt";


    copyFile(inFp, inFpCrc);
    //appendZeroes(inFpZeroes, SIZECRC);
    unsigned char * restPoly = calculateCrc(inFp);
    printf("Generated polynomial:\n");
    printPolynomial(restPoly, SIZECRC);

    appendCrcToFile(inFpCrc, SIZECRC, restPoly);

    int lettersFrequencies[LETTERS_COUNT]; // = {81, 15, 28, 43, 128, 23, 20, 61, 71, 2, 1, 40, 24, 69, 76, 20, 1, 61, 64, 91, 28, 10, 24, 1, 20, 1, 130};;
    //char letters[LETTERS_COUNT] = {'?', '?', '?', '?', '?', '?', '?', '?', '?', '?','?', '?', '?', '?', '?','?', '?', '?', '?', '?','?', '?', '?', '?', '?','?', '?', '?', '?', '?', '?', '?', '!', '"', '#', '$', '%', '&', '(', ')', '*', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' '};
    //printTabInt(lettersFrequencies, LETTERS_COUNT);
    //printTabChar(letters, LETTERS_COUNT);

    //printf("Letter indices: ");

    calculateFreq(inFpCrc, lettersFrequencies);
    //printTabInt(lettersFrequencies, 255);

    Node *nodes[LETTERS_COUNT];
    int i;
    for(i=0; i<LETTERS_COUNT; i++)
    {
        nodes[i] = malloc(sizeof(Node));
        nodes[i]->value = lettersFrequencies[i];
        nodes[i]->letterIndex = i;
        nodes[i]->left = NULL;
        nodes[i]->right = NULL;
    }

    //printLetterIndices(nodes);
    Node *tree = buildHuffmanTree(nodes);

    int codeTable[LETTERS_COUNT];
    int invertedCodeTable2[LETTERS_COUNT];
    resetIntTable(codeTable, LETTERS_COUNT);

    //printf("codeTable: \n");
    //printTabInt(codeTable, LETTERS_COUNT);
    fillTable(codeTable, tree, 0);
    invertCodeTable(codeTable, invertedCodeTable2);


    //printf("codeTable: \n");
    //printTabInt(codeTable, LETTERS_COUNT);

    //printf("inverted codeTable: \n");
    //printTabInt(invertedCodeTable2, LETTERS_COUNT);
    //printCodeTable(letters, codeTable, LETTERS_COUNT);
    //printCodeTableForIdx(codeTable, LETTERS_COUNT);
    //printTabInt(codeTable, LETTERS_COUNT);




    //createCrcFile(inFpCrc, SIZECRC, restPoly);
    //appendFileToFile(inFp, inFpCrc);



    compressFile(inFpCrc, outFp, invertedCodeTable2);
    printf("\n\ndecompressed file:\n");
    decompressFile(outFp, decompressedFpCrc, tree);

    unsigned char * restPolyFromDec = calulateRest(decompressedFpCrc);
    printf("\n\nRest from decopressed file:\n");
    printPolynomial(restPolyFromDec, SIZECRC);

    if(!isIntegral()){
        printf("Integrity check failed!");
        exit(EXIT_FAILURE);
    }else{
        copySkip(decompressedFpCrc, decompressedFp, SIZECRC);
    }

    //checkIntegrity();


    //FILE * output = fopen("C:\\codeblocks\\Huffman\\huffman\\to.txt","w");
    //compressFile(input, output, codeTable);


    return 0;
}
main(int argc, char* argv[]){
	clock_t start, end;
	unsigned int cpu_time_used;
	unsigned int i, j, rank, numProcesses, blockLength;
	unsigned int *compBlockLengthArray;
	unsigned int distinctCharacterCount, combinedHuffmanNodes, frequency[256], inputFileLength, compBlockLength;
	unsigned char *inputFileData, *compressedData, writeBit = 0, bitsFilled = 0, bitSequence[255], bitSequenceLength = 0;
	FILE *inputFile;

	MPI_Init( &argc, &argv);
	MPI_File mpi_inputFile, mpi_compressedFile;
	MPI_Status status;

	// get rank and number of processes value
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &numProcesses);

	// get file size
	if(rank == 0){
		inputFile = fopen(argv[1], "rb");
		fseek(inputFile, 0, SEEK_END);
		inputFileLength = ftell(inputFile);
		fseek(inputFile, 0, SEEK_SET);
		fclose(inputFile);
	}

	//broadcast size of file to all the processes 
	MPI_Bcast(&inputFileLength, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD);

	// get file chunk size

	blockLength = inputFileLength / numProcesses;

	if(rank == (numProcesses-1)){
		blockLength = inputFileLength - ((numProcesses-1) * blockLength);	
	}
	
	// open file in each process and read data and allocate memory for compressed data
	MPI_File_open(MPI_COMM_WORLD, argv[1], MPI_MODE_RDONLY, MPI_INFO_NULL, &mpi_inputFile);
	MPI_File_seek(mpi_inputFile, rank * blockLength, MPI_SEEK_SET);

	inputFileData = (unsigned char *)malloc(blockLength * sizeof(unsigned char));	
	MPI_File_read(mpi_inputFile, inputFileData, blockLength, MPI_UNSIGNED_CHAR, &status);

	// start clock
	if(rank == 0){
		start = clock();
	}
	
	// find the frequency of each symbols
	for (i = 0; i < 256; i++){
		frequency[i] = 0;
	}
	for (i = 0; i < blockLength; i++){
		frequency[inputFileData[i]]++;
	}
	
	compressedData = (unsigned char *)malloc(blockLength * sizeof(unsigned char));	
	compBlockLengthArray = (unsigned int *)malloc(numProcesses * sizeof(unsigned int));
	
	// initialize nodes of huffman tree
	distinctCharacterCount = 0;
	for (i = 0; i < 256; i++){
		if (frequency[i] > 0){
			huffmanTreeNode[distinctCharacterCount].count = frequency[i];
			huffmanTreeNode[distinctCharacterCount].letter = i;
			huffmanTreeNode[distinctCharacterCount].left = NULL;
			huffmanTreeNode[distinctCharacterCount].right = NULL;
			distinctCharacterCount++;
		}
	}

	// build tree 
	for (i = 0; i < distinctCharacterCount - 1; i++){
		combinedHuffmanNodes = 2 * i;
		sortHuffmanTree(i, distinctCharacterCount, combinedHuffmanNodes);
		buildHuffmanTree(i, distinctCharacterCount, combinedHuffmanNodes);
	}
	
	// build table having the bitSequence sequence and its length
	buildHuffmanDictionary(head_huffmanTreeNode, bitSequence, bitSequenceLength);

	// compress
	compBlockLength = 0;
	for (i = 0; i < blockLength; i++){
		for (j = 0; j < huffmanDictionary[inputFileData[i]].bitSequenceLength; j++){
			if (huffmanDictionary[inputFileData[i]].bitSequence[j] == 0){
				writeBit = writeBit << 1;
				bitsFilled++;
			}
			else{
				writeBit = (writeBit << 1) | 01;
				bitsFilled++;
			}
			if (bitsFilled == 8){
				compressedData[compBlockLength] = writeBit;
				bitsFilled = 0;
				writeBit = 0;
				compBlockLength++;
			}
		}
	}

	if (bitsFilled != 0){
		for (i = 0; (unsigned char)i < 8 - bitsFilled; i++){
			writeBit = writeBit << 1;
		}
		compressedData[compBlockLength] = writeBit;
		compBlockLength++;
	}

	// calculate length of compressed data
	compBlockLength = compBlockLength + 1024;
	compBlockLengthArray[rank] = compBlockLength;

	// send the length of each process to process 0
	MPI_Gather(&compBlockLength, 1, MPI_UNSIGNED, compBlockLengthArray, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD);

	// update the data to reflect the offset
	if(rank == 0){
		compBlockLengthArray[0] = (numProcesses + 2) * 4 + compBlockLengthArray[0];
		for(i = 1; i < numProcesses; i++){
			compBlockLengthArray[i] = compBlockLengthArray[i] + compBlockLengthArray[i - 1];
		}
		for(i = (numProcesses - 1); i > 0; i--){
			compBlockLengthArray[i] = compBlockLengthArray[i - 1];
		}
		compBlockLengthArray[0] = (numProcesses + 2) * 4;
	}

	// broadcast size of each compressed data block to all the processes 
	MPI_Bcast(compBlockLengthArray, numProcesses, MPI_UNSIGNED, 0, MPI_COMM_WORLD);

	// get time
	if(rank == 0){
		end = clock();
		cpu_time_used = ((end - start)) * 1000 / CLOCKS_PER_SEC;
		printf("Time taken: %d:%d s\n", cpu_time_used / 1000, cpu_time_used % 1000);
	}
	
	// write data to file
	MPI_File_open(MPI_COMM_WORLD, argv[2], MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &mpi_compressedFile);

	if(rank == 0){
		MPI_File_write(mpi_compressedFile, &inputFileLength, 1, MPI_UNSIGNED, MPI_STATUS_IGNORE);
		MPI_File_write(mpi_compressedFile, &numProcesses, 1, MPI_UNSIGNED, MPI_STATUS_IGNORE);
		MPI_File_write(mpi_compressedFile, compBlockLengthArray, numProcesses, MPI_UNSIGNED, MPI_STATUS_IGNORE);
	}
	MPI_File_seek(mpi_compressedFile, compBlockLengthArray[rank], MPI_SEEK_SET);
	MPI_File_write(mpi_compressedFile, frequency, 256, MPI_UNSIGNED, MPI_STATUS_IGNORE);
	MPI_File_write(mpi_compressedFile, compressedData, (compBlockLength - 1024), MPI_UNSIGNED_CHAR, MPI_STATUS_IGNORE);

	// close open files
	MPI_File_close(&mpi_compressedFile); 	
	MPI_File_close(&mpi_inputFile);
	MPI_Barrier(MPI_COMM_WORLD);
	
	free(head_huffmanTreeNode);
	free(current_huffmanTreeNode);
	free(compBlockLengthArray);
	free(inputFileData);
	free(compressedData);
	MPI_Finalize();
}