gt: 		String line = lines[i];
context: package com.github.distanteye.ep_utils.core;
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.nio.charset.Charset;
  import java.nio.file.FileSystems;
  import java.nio.file.Files;
  import java.nio.file.Path;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
  import org.apache.commons.lang3.StringUtils;
  
  // explicit because name ambiguity
  import com.github.distanteye.ep_utils.containers.*;
  import com.github.distanteye.ep_utils.core.Package;
  
  /**
   * The DataFileProcessor class serves to take commands to look up a particular table,
   * and results in the right table (from text files) being called up, and the appropriate
   * action being processed
   * 
   * @author Vigilant
   *
   */
  public class DataProc {
  	
  	// we keep these incase later versions need to write to datafiles
  	private static HashMap<String, UniqueNamedData> dataStore; // local copy of any data built by this app
  	private static int fileLineNumber;
  	
  
  	/**
  	 * Takes data files as parameters and builds the environment needed for char-gen to work
  	 * @param lpFileName holds packages/tables/etc needed for the lifepath and/or package system
  	 * @param internalDatFile holds things like skills, rep, gear, etc, each setup so that getNextChunk can parse from it
  	 */
  	public static void init(String lpFileName, String internalDatFile) {
  		dataStore = new HashMap<String, UniqueNamedData>();
  		readIntData(internalDatFile);
  		readLPData(lpFileName);
  		fileLineNumber = -1; // reset when we're done
  	}
  
  	
  	private static void readIntData(String filename)
  	{
  		Path path = FileSystems.getDefault().getPath("data", filename);
  		fileLineNumber = 0;
  		
  		Charset charset = Charset.forName("UTF-8");
  		try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
  		    buildData(reader);
  		    reader.close();
  		} catch (IOException x) {
  		    System.err.format("Could not find file: %s%n", x);
  		    System.exit(-1);
  		}
  	}
  	
  	
  	
  	
  	// ?1? ?2? ?3? and / has to be coded to read in skills, aptitudes, skill subtypes, everything. try and make it all work
  		// throw an error if you can't read something, the reading should be perfect, or we want to know about it if it's not
  	
  	private static void readLPData(String filename)
  	{
  		Path path = FileSystems.getDefault().getPath("data", filename);
  		fileLineNumber = 0;
  		
  		Charset charset = Charset.forName("UTF-8");
  		try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
  		    buildData(reader);
  		    reader.close();
  		} catch (IOException x) {
  		    System.err.format("Could not find file: %s%n", x);
  		    System.exit(-1);
  		}
  	}
  
  	/**
  	 * Takes an appropriately opened reader and builds all necessary lifepath data from it
  	 * @param reader Needs to be already set to a file or errors will result
  	 * @throws IOException If there are any problems with the reader 
  	 */
  	private static void buildData(BufferedReader reader) throws IOException 
  	{
  		// get the next chunk of data (always separated by a long set of dashes)
  		String[] chunk = getNextChunk(reader);
  		
  		while (chunk != null && chunk[0].length() > 0)
  		{
  			if (chunk[0].equalsIgnoreCase("rep") && chunk.length > 1)
  			{
  				for (int x = 1; x < chunk.length; x++)
  				{
  					Rep.addRepType(chunk[x]);
  				}
  			}
  			else if (chunk[0].equalsIgnoreCase("skill") && chunk.length > 1)
  			{
  				for (int x = 1; x < chunk.length; x++)
  				{
  					Skill.CreateInternalSkill(chunk[x]);
  				}
  			}
  			else if (chunk[0].equalsIgnoreCase("package") && chunk.length > 1)
  			{
  				addPackage(chunk);
  			}
  			else if (chunk[0].equalsIgnoreCase("morph") && chunk.length > 1)
  			{
  				addMorph(chunk);
  			}
  			else if (chunk[0].equalsIgnoreCase("table") && chunk.length > 1)
  			{
  				addTable(chunk);
  			}
  			else if (chunk[0].equalsIgnoreCase("function") && chunk.length > 1)
  			{
  				addFunction(chunk);
  			}
  			else if (chunk[0].equalsIgnoreCase("trait") && chunk.length > 1)
  			{
  				addTrait(chunk);
  			}
  			else if (chunk[0].equalsIgnoreCase("sleight") && chunk.length > 1)
  			{
  
  				addSleight(chunk);
  			
  			}
  			else if (chunk[0].equalsIgnoreCase("step") && chunk.length > 1)
  			{
  
  				addStep(chunk);
  			
  			}
  			else if (chunk[0].equalsIgnoreCase("charvars") && chunk.length > 1)
  			{
  				for (int i = 1; i< chunk.length; i++)
  				{
  					String[] parts = chunk[i].split(":");
  					if (parts.length == 2)
  					{
  						EpCharacter.charConstants.put(parts[0], parts[1]);
  					}
  					else
  					{
  						throw new IllegalArgumentException("Improperly formated charvar at line : " + fileLineNumber + " (" + chunk[i] +")");
  					}
  				}
  			}
  			else
  			{
  				throw new IllegalArgumentException("Unknown type of data or incorrect formating at line : " + fileLineNumber);
  			}
  			
  			chunk = getNextChunk(reader);
  		}
  		
  	}
  	
  	/**
  	 * Takes an appropriately opened reader and returns the next batch of lines until
  	 * a long trail of dashes is read (signifying the end of the dash)
  	 * @param reader Needs to be already set to a file or errors will result
  	 * @return Either an array of Strings (lines), or null, if no more exists on the file
  	 * @throws IOException If there are any problems with the reader
  	 */
  	private static String[] getNextChunk(BufferedReader reader) throws IOException
  	{
  		ArrayList<String> lines = new ArrayList<String>();
  		
  		
  		String line = reader.readLine();
  		fileLineNumber++;
  		// this will always chop off the next ---------- type line found at the end by reading and then discarding it
  		// so the next time getNextChunk is called it never sees that line
  		while (line != null && !line.startsWith("----------------") )
  		{
  			if (!line.startsWith("//"))
  			{
  				lines.add(line);
  			}
  			
  			line = reader.readLine();
  			fileLineNumber++;
  		}
  		
  		if (lines.size() < 2 ) // The lines must exist and be at least one line long
  		{
  			return null;
  		}
  		
  		return lines.toArray(new String[lines.size()]);
  	}
  	
  	/**
  	 * Adds Package to the system
  	 * Format:
  	 * Line 1 : PACKAGE
  	 * Line 2 : The package's name
  	 * Line 3 : Human readable description of package
  	 * Line 4+ : Rest lines follow format PP;NUM>effects  , where NUM is a positive integer and effects is a valid effects string
  	 * Line * : A line at the end starting with * can be used to add special contextual notes to the package
  	 * @param lines
  	 */
  	private static void addPackage(String[] lines)
  	{
  		// first line just says package, we can ignore
  		
  		// second line is package name
  		String name = lines[1];
  		
  		// third line is human text description (can be empty)
  		String desc = lines[2];
  		
  		// fourth line is the suggested motivations (can be empty)
  		String motiv = lines[3];
  		
  		// remaining lines are the different effects by package PP, some packages only have PP1, others have PP1,PP3, PP5, etc
  		int i = 4;
  