public void diff(KeyGenerator leftKeyGenerator, KeyGenerator rightKeyGenerator, Filter leftFilter, 
			Filter rightFilter, String leftFile, String rightFile, String resultFile) throws IOException
	{
		if (leftKeyGenerator == null) leftKeyGenerator = config.getLeftKeyGenerator();
		if (rightKeyGenerator == null) rightKeyGenerator = config.getRightKeyGenerator();
		
		TxtTable leftT = new TxtTable(leftFile, leftKeyGenerator, leftFilter, 
				false, config.getLeftDelimiter(), config.getLeftEscape());
		leftT.setPrimaryFields(config.getLeftPrimaryFields());
		
		TxtTable rightT = new TxtTable(rightFile, rightKeyGenerator, rightFilter,
				false, config.getRightDelimiter(), config.getRightEscape());
		rightT.setPrimaryFields(config.getRightPrimaryFields());
		
		DiffResults result = new DiffResults(resultFile);
	
		TxtTable.Row leftRow = leftT.getNextRow();
		TxtTable.Row rightRow = rightT.getNextRow();
		
		while(leftRow != null && rightRow != null)
		{
			leftRow = handleDuplicates(result, leftT, preLeftRow, leftRow, false);
			rightRow = handleDuplicates(result, rightT, preRightRow, rightRow, true);
			
			@SuppressWarnings("unchecked")
			int compare = leftRow.getKey().compareTo(rightRow.getKey());
			
			if (compare < 0)
			{
				// right side is missing
				result.addRightMiss(leftRow);
				preLeftRow = leftRow;
				leftRow = leftT.getNextRow();
				continue;
			}
			else if (compare > 0)
			{
				// left side is missing
				result.addLeftMiss(rightRow);
				preRightRow = rightRow;
				rightRow = rightT.getNextRow();
				continue;
			}

			// key matched, compare content
			
			String msg = null;
			
			try
			{
				msg = rowComparator.compare(leftT, leftRow, rightT, rightRow);
			
				if (msg != null)
				{
					result.addMessage(msg);
					result.addMismatch(leftRow, rightRow);
				}
			}
			catch (Exception e)
			{
				result.addMessage(e.toString());
				result.addMismatch(leftRow, rightRow);
			}
			
			preLeftRow = leftRow;
			preRightRow = rightRow;
			
			leftRow = leftT.getNextRow();
			rightRow = rightT.getNextRow();
		}
		
		checkMissing(result, leftT, leftRow, false);
		checkMissing(result, rightT, rightRow, true);
		
		leftT.closeFile();
		rightT.closeFile();
		
		result.addSummary();
		result.close();
	}