@Override
	public void encode() throws IOException {
		System.out.println("Starting compression of file \"" + sourceFile.getFileName() + "\" to \"" + destinationFile.getFileName() + "\"");
		totalTimer = new Timer().start();
		// Count the number of occurences of each character in the file
		printMessage("Counting characters in file " + sourceFile.getFileName() + "... ");
		countCharactersInFile();
		printTime();

		// Build the tree from this count
		printMessage("Building Huffman Tree from character count... ");
		buildTree();
		printTime();

		// Get the character codes from the tree
		printMessage("Generating character codes from tree... ");
		sortedCodes = huffmanTree.getCharacterCodes();
		printTime();

		if (sortedCodes.size() == 0) {
			throw new IllegalArgumentException("Why do you want to compress an empty file ?");
		} else if (sortedCodes.size() == 1) {
			handleOneCharFile(sortedCodes.pollFirst().getChar());
		}
		// Write the Tree to the file
		printMessage("Writing tree string representation as output file header... ");
		writeTree();
		printTime();

		// Create the codesArray for encoding
		createCodeArray();
		// Encode source file
		printMessage("Encoding source file... ");
		try (final BufferedReader reader = Files.newBufferedReader(sourceFile, CHARSET);
				final FileOutputStream writer = new FileOutputStream(destinationFile.toFile(), true)) {
			final char[] readBuffer = new char[8192];
			// Char size = 1 byte
			// CharacterCodes max length : 256 differents chars, max length = 256
			// So a buffer with a size equals to the char buffer is enough
			final BitArray writeBuffer = new BitArray(8192);
			int length;
			do {
				length = reader.read(readBuffer);
				for (int i = 0; i < length; i++) {
					writeBuffer.add(codesArray[readBuffer[i]]);
				}
				writer.write(writeBuffer.pollByteArray()); //pollByteArray removes the bytes it returns
			} while (length == readBuffer.length);
			if (writeBuffer.hasRemainingByte()) {
				// Last byte does not contain 8 interesting bits
				final int lastByteLength = writeBuffer.getLastByteLength();
				writer.write(writeBuffer.getLastByte()); //write the last byte
				writer.write((byte) Byte.SIZE - lastByteLength);//write the number of interesting bits in the last byte
			} else {
				// Last byte is full
				writer.write(0x00);
			}
		}
		printTime();
		System.out.println("Compression successful !\n    Time: " + totalTimer.stop().diffString() + "\n    Compression rate: "
				+ new DecimalFormat("#0.00").format(100 - 100.0 * Files.size(destinationFile) / Files.size(sourceFile)) + "%");
	}