diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/App.java b/src/main/java/de/tudresden/inf/mci/brailleplot/App.java
index b7ee3097e4e621375eba2c7e42249a2520e1cdc1..66ed57bf2762012f4cf3b8e19dc5198f214cf1e0 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/App.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/App.java
@@ -42,6 +42,7 @@ import tec.units.ri.unit.MetricPrefix;
 import javax.measure.Quantity;
 import javax.measure.quantity.Length;
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
@@ -166,9 +167,30 @@ public final class App {
             }
 
             // Config Parsing
+            String configPath;
+            if (!settingsReader.isPresent(SettingType.PRINTER_CONFIG_PATH)) { // TODO: exception if missing this argument
+                configPath = this.getClass().getResource("/config/index_everest_d_v4.properties").getFile();
+                mLogger.info("Using default file: " + configPath);
+                if (!(new File(configPath)).isFile()) {
+                    mLogger.info("Does not exist!");
+                }
+            } else {
+                configPath = settingsReader.getSetting(SettingType.PRINTER_CONFIG_PATH).get();
+            }
+
+            /*
+            GeneralResource testResource = new GeneralResource("/config/default.properties");
+            if (testResource.isValidExternalFile()) {
+                File testFile = testResource.asValidExternalFile();
+            } else {
+                InputStream testStream = testResource.asInputStream();
+            }
+
+             */
+
             JavaPropertiesConfigurationParser configParser = new JavaPropertiesConfigurationParser(
-                    getClass().getClassLoader().getResource("config/index_everest_d_v4.properties").getFile(),
-                    getClass().getClassLoader().getResource("config/default.properties").getFile()
+                    configPath,
+                    "/config/default.properties"
             );
             Printer indexV4Printer = configParser.getPrinter();
             Format a4Format = configParser.getFormat("A4");
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/GeneralResource.java b/src/main/java/de/tudresden/inf/mci/brailleplot/GeneralResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf5a2bf49068fae604358ded4720ab22054cb765
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/GeneralResource.java
@@ -0,0 +1,137 @@
+package de.tudresden.inf.mci.brailleplot;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * This class is used to use files & resources independent from the application running from packed jar or not.
+ * @author Leonard Kupper
+ * @version 2019-09-10
+ */
+public final class GeneralResource {
+
+    private String mResourcePath;
+    private boolean validExternalFile = false;
+    private boolean validPackedResource = false;
+    Logger mLogger = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * Create a resource from a file path or resource classpath.
+     * @param resourcePath Relative or local path to a file (e.g. C:\example.txt) in the filesystem or classpath pointing to (packed) resource location (e.g. /config/default.properties)
+     * @throws IOException If the given path neither determines a valid external file, nor a valid resource.
+     */
+    public GeneralResource(final String resourcePath) throws IOException {
+        this(resourcePath, null);
+    }
+
+    /**
+     * Create a resource from a file path or resource classpath.
+     * @param resourcePath Relative or local path to a file (e.g. C:\example.txt) in the filesystem or classpath pointing to (packed) resource location (e.g. /config/default.properties)
+     * @param searchPath Relative or local path to be used as base for interpreting the resourcePath relatively to additionally.
+     * @throws IOException If the given path neither determines a valid external file, nor a valid resource.
+     */
+    public GeneralResource(final String resourcePath, final String searchPath) throws IOException {
+        File checkFile = new File(resourcePath);
+        mLogger.info("checking referenced path: " + checkFile);
+        if (checkFile.isFile()) {
+            mLogger.info("interpreting path as file: " + checkFile.getCanonicalPath());
+            mResourcePath = checkFile.getCanonicalPath();
+            validExternalFile = true;
+        }
+        checkFile = checkFile.getAbsoluteFile();
+        mLogger.info("checking referenced path as absolute path: " + checkFile);
+        if (checkFile.isFile()) {
+            mLogger.info("interpreting path as absolute file: " + checkFile.getCanonicalPath());
+            mResourcePath = checkFile.getCanonicalPath();
+            validExternalFile = true;
+        }
+        if (Objects.nonNull(searchPath)) {
+            checkFile = new File(searchPath + File.separator + resourcePath);
+            mLogger.info("looking for referenced path in search path: " + checkFile);
+            if (checkFile.isFile()) {
+                mLogger.info("interpreting path as search path relative file: " + checkFile.getCanonicalPath());
+                mResourcePath = checkFile.getCanonicalPath();
+                validExternalFile = true;
+            }
+        }
+        String resourceClassPath = resourcePath.replace("\\", "/"); // classpaths are always separated by forward slash
+        InputStream checkStream = getClass().getResourceAsStream(resourceClassPath);
+        mLogger.info("checking referenced path as resource: " + resourceClassPath);
+        if (Objects.nonNull(checkStream)) {
+            mLogger.info("interpreting path as resource stream: " + resourceClassPath);
+            mResourcePath = resourceClassPath;
+            validPackedResource = true;
+        }
+        if (Objects.nonNull(searchPath)) {
+            String relativeResourcePath = new File(searchPath + File.separator + resourceClassPath).toPath().normalize().toString();
+            relativeResourcePath = relativeResourcePath.replace("\\", "/");
+            checkStream = getClass().getResourceAsStream(relativeResourcePath);
+            mLogger.info("checking referenced path as search path relative resource: " + relativeResourcePath);
+            if (Objects.nonNull(checkStream)) {
+                mLogger.info("interpreting path as resource stream: " + relativeResourcePath);
+                mResourcePath = relativeResourcePath;
+                validPackedResource = true;
+            }
+        }
+        if (!(isValidExternalFile() || isValidPackedResource())) {
+            throw new FileNotFoundException("Not recognized as valid file or resource: " + resourcePath);
+        }
+    }
+
+    public boolean isValidExternalFile() {
+        return validExternalFile;
+    }
+
+    public boolean isValidPackedResource() {
+        return validPackedResource;
+    }
+
+    public InputStream asInputStream() {
+        try {
+            if (isValidExternalFile()) {
+                return new FileInputStream(getResourcePath());
+            }
+            return getClass().getResourceAsStream(mResourcePath);
+        } catch (Exception e) {
+            throw new RuntimeException("Error while opening resource as stream: ", e);
+        }
+    }
+
+    public File asValidExternalFile() {
+        if (!isValidExternalFile()) {
+            throw new IllegalArgumentException("Not a valid external file: " + getResourcePath());
+        }
+        return new File(getResourcePath());
+    }
+
+    public String getResourcePath() {
+        return mResourcePath;
+    }
+
+    public File getFileOrExportResource() {
+        if (!isValidPackedResource()) {
+            return asValidExternalFile();
+        } else {
+            try {
+                File tmpOut = File.createTempFile("resource_" + UUID.randomUUID(), "tmp");
+                byte[] content = asInputStream().readAllBytes();
+                FileOutputStream outputStream = new FileOutputStream(tmpOut);
+                outputStream.write(content);
+                outputStream.close();
+                return tmpOut;
+            } catch (IOException e) {
+                throw new RuntimeException("Error while exporting resource: ", e);
+            }
+        }
+    }
+
+}
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/ConfigurationParser.java b/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/ConfigurationParser.java
index 54284b1a68598478f5bf7df98ad5b562976b8268..bdd14b694134e933355410cd845d1c23ee7b9b7f 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/ConfigurationParser.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/ConfigurationParser.java
@@ -1,13 +1,18 @@
 package de.tudresden.inf.mci.brailleplot.configparser;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -28,8 +33,10 @@ public abstract class ConfigurationParser {
     private Printer mDefaultPrinter;
     private Format mDefaultFormat;
 
-    ConfigurationParser() {
+    private final Logger mLogger;
 
+    ConfigurationParser() {
+        mLogger = LoggerFactory.getLogger(this.getClass());
     };
 
     /**
@@ -42,7 +49,7 @@ public abstract class ConfigurationParser {
      * @throws ConfigurationParsingException On any error while accessing the configuration file or syntax.
      * @throws ConfigurationValidationException On any error while checking the parsed properties validity.
      */
-    protected abstract void parse(FileInputStream input) throws ConfigurationParsingException, ConfigurationValidationException;
+    protected abstract void parse(InputStream input) throws ConfigurationParsingException, ConfigurationValidationException;
 
 
     /**
@@ -147,8 +154,8 @@ public abstract class ConfigurationParser {
         mFormatProperties.clear();
         // load and parse file
         mCurrentConfigFile = new File(filePath);
-        FileInputStream input = openInputStream(filePath);
-        getValidator().setSearchPath(getConfigFile().getParentFile().getAbsolutePath());
+        InputStream input = openInputStream(filePath);
+        getValidator().setSearchPath(Objects.requireNonNullElse(getConfigFile().getParent(), ""));
         parse(input);
         closeInputStream(input);
         // build printer object from added properties
@@ -178,11 +185,23 @@ public abstract class ConfigurationParser {
      * @return A {@link FileInputStream} for the given file path.
      * @throws ConfigurationParsingException On any error while opening the stream. (e.g. missing file)
      */
-    final FileInputStream openInputStream(final String filePath) throws ConfigurationParsingException {
+    final InputStream openInputStream(final String filePath) throws ConfigurationParsingException {
+        // This has to take the fact into consideration, that a resource from a packaged jar is not a real file in
+        // the file system and must be read via classloader resource stream.  We want to be able to process files as
+        // well as packed resources.
         try {
+            // first try to read as file
+            mLogger.info("trying to open as file: " + filePath);
             return new FileInputStream(filePath);
         } catch (IOException e) {
-            throw new ConfigurationParsingException("Unable to read configuration file", e);
+            // if that fails, try to read as resource
+            mLogger.info("trying to open as resource: " + filePath);
+            InputStream resourceStream = this.getClass().getResourceAsStream(filePath);
+            if (Objects.isNull(resourceStream)) {
+                // if that also fails:
+                throw new ConfigurationParsingException("Unable to read configuration file / resource.", e);
+            }
+            return resourceStream;
         }
     }
 
@@ -191,7 +210,7 @@ public abstract class ConfigurationParser {
      * @param input The {@link FileInputStream} to be closed.
      * @throws ConfigurationParsingException On any error while closing the stream.
      */
-    final void closeInputStream(final FileInputStream input) throws ConfigurationParsingException {
+    final void closeInputStream(final InputStream input) throws ConfigurationParsingException {
         try {
             input.close();
         } catch (IOException e) {
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationParser.java b/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationParser.java
index 31e9fc794280ada718e60d3dda1bbc635a4ec1c5..39611e2397549052991b5f6823219e8e2453788b 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationParser.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationParser.java
@@ -1,8 +1,12 @@
 package de.tudresden.inf.mci.brailleplot.configparser;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.util.Objects;
 import java.util.Properties;
 import java.util.Stack;
 
@@ -14,6 +18,7 @@ import java.util.Stack;
 public final class JavaPropertiesConfigurationParser extends ConfigurationParser {
 
     Stack<File> mInclusionStack = new Stack<>();
+    private final Logger mLogger;
 
     /**
      * Constructor.
@@ -28,6 +33,7 @@ public final class JavaPropertiesConfigurationParser extends ConfigurationParser
             final String filePath,
             final String defaultPath
     ) throws ConfigurationParsingException, ConfigurationValidationException {
+        mLogger = LoggerFactory.getLogger(this.getClass());
         setValidator(new JavaPropertiesConfigurationValidator());
         parseConfigFile(defaultPath, false);
         setDefaults(getPrinter(), getFormat("default"));
@@ -41,7 +47,7 @@ public final class JavaPropertiesConfigurationParser extends ConfigurationParser
      * @throws ConfigurationParsingException On any error while accessing the configuration file or syntax.
      * @throws ConfigurationValidationException On any error while checking the parsed properties validity.
      */
-    protected void parse(final FileInputStream input) throws ConfigurationParsingException, ConfigurationValidationException {
+    protected void parse(final InputStream input) throws ConfigurationParsingException, ConfigurationValidationException {
         // Create property instance for current recursion level
         Properties properties = new Properties();
         try {
@@ -77,7 +83,7 @@ public final class JavaPropertiesConfigurationParser extends ConfigurationParser
             if (mInclusionStack.empty()) {
                 mInclusionStack.push(getConfigFile());
             }
-            File includeFile, parentFile = mInclusionStack.peek().getParentFile();
+            File includeFile, parentFile = Objects.requireNonNullElse(mInclusionStack.peek().getParentFile(), new File(""));
             try {
                 String findIncludePath = parentFile.getAbsolutePath() + File.separator + includeName.trim();
                 File abstractPath = new File(findIncludePath);
@@ -94,13 +100,14 @@ public final class JavaPropertiesConfigurationParser extends ConfigurationParser
             if (mInclusionStack.contains(includeFile)) {
                 continue;
             }
-            FileInputStream includeInput = openInputStream(includeFile.getAbsolutePath());
+            InputStream includeInput = openInputStream(includeFile.getAbsolutePath());
             try {
                 mInclusionStack.push(includeFile);
-                getValidator().setSearchPath(mInclusionStack.peek().getParentFile().getAbsolutePath());
+                mLogger.info("Including config file: " + includeFile);
+                getValidator().setSearchPath(Objects.requireNonNullElse(mInclusionStack.peek().getParent(), ""));
                 parse(includeInput);
                 mInclusionStack.pop();
-                getValidator().setSearchPath(mInclusionStack.peek().getParentFile().getAbsolutePath());
+                getValidator().setSearchPath(Objects.requireNonNullElse(mInclusionStack.peek().getParent(), ""));
             } finally {
                 closeInputStream(includeInput);
             }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationValidator.java b/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationValidator.java
index fac80641bb465377dc29171a9e6ae897d4150121..33542e992ff20efb8a6ac365f4bedba66922259f 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationValidator.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/configparser/JavaPropertiesConfigurationValidator.java
@@ -1,13 +1,11 @@
 package de.tudresden.inf.mci.brailleplot.configparser;
 
 
+import de.tudresden.inf.mci.brailleplot.GeneralResource;
 import de.tudresden.inf.mci.brailleplot.printerbackend.PrinterCapability;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
@@ -87,7 +85,7 @@ public final class JavaPropertiesConfigurationValidator implements Configuration
     private String interpretProperty(final String propertyName, final String value) throws ConfigurationValidationException {
         try {
             switch (propertyName) {
-                case "brailletable": return checkFileLocation(value);
+                case "brailletable": return new GeneralResource(value, mSearchPath).getResourcePath();
                 default: return value;
             }
         } catch (Exception e) {
@@ -95,30 +93,31 @@ public final class JavaPropertiesConfigurationValidator implements Configuration
         }
     }
 
-    /**
-     * This will first check the given file path if it exists as it is, else interpret as absolute, else relative to the set search path.
-     * @param path The file path to be checked. (Must be a file, not directory!)
-     * @return The interpreted path string to an existing file.
-     * @throws FileNotFoundException If all options to interpret the path string result in non-existing files.
-     */
-    private String checkFileLocation(final String path) throws FileNotFoundException {
+/**
+ * This will first check the given file path if it exists as it is, else interpret as absolute, else relative to the set search path.
+ * @param path The file path to be checked. (Must be a file, not directory!)
+ * @return The interpreted path string to an existing file.
+ * @throws IOException If all options to interpret the path string result in non-existing files.
+ */
+    /*
+    private String checkFileLocation(final String path) throws IOException {
         File checkFile = new File(path);
         mLogger.info("checking referenced path: " + checkFile);
         if (checkFile.isFile()) {
-            mLogger.info("interpreting path as file: " + checkFile.getAbsolutePath());
+            mLogger.info("interpreting path as file: " + checkFile.getCanonicalPath());
             return checkFile.getAbsolutePath();
         }
         checkFile = checkFile.getAbsoluteFile();
         mLogger.info("checking referenced path as absolute path: " + checkFile);
         if (checkFile.isFile()) {
-            mLogger.info("interpreting path as absolute file: " + checkFile.getAbsolutePath());
+            mLogger.info("interpreting path as absolute file: " + checkFile.getCanonicalPath());
             return checkFile.getAbsolutePath();
         }
         if (Objects.nonNull(mSearchPath)) {
             checkFile = new File(mSearchPath + File.separator + path);
             mLogger.info("looking for referenced path in search path: " + checkFile);
             if (checkFile.isFile()) {
-                mLogger.info("interpreting path as search path relative file: " + checkFile.getAbsolutePath());
+                mLogger.info("interpreting path as search path relative file: " + checkFile.getCanonicalPath());
                 return checkFile.getAbsolutePath();
             }
         }
@@ -128,8 +127,16 @@ public final class JavaPropertiesConfigurationValidator implements Configuration
             mLogger.info("interpreting path as resource stream: " + path);
             return path;
         }
+        String relativeResourcePath = mSearchPath + File.separator + path;
+        checkStream = getClass().getClassLoader().getResourceAsStream(relativeResourcePath);
+        mLogger.info("checking referenced path as relative resource: " + relativeResourcePath);
+        if (Objects.nonNull(checkStream)) {
+            mLogger.info("interpreting path as resource stream: " + relativeResourcePath);
+            return path;
+        }
         throw new FileNotFoundException("File/Resource not found: " + path);
     }
+     */
 
     @Override
     public void setSearchPath(final String searchPath) {
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java
index 9863e424b3fac215c7d3c15c8546cddbdb193f76..b4935de4f45a2f7056d7cfdd74293ae69013e2aa 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java
@@ -1,5 +1,6 @@
 package de.tudresden.inf.mci.brailleplot.rendering;
 
+import de.tudresden.inf.mci.brailleplot.GeneralResource;
 import de.tudresden.inf.mci.brailleplot.brailleparser.AbstractBrailleTableParser;
 import de.tudresden.inf.mci.brailleplot.configparser.Printer;
 import de.tudresden.inf.mci.brailleplot.layout.InsufficientRenderingAreaException;
@@ -12,6 +13,8 @@ import org.liblouis.TranslationException;
 import org.liblouis.TranslationResult;
 import org.liblouis.Translator;
 
+import java.io.File;
+import java.nio.file.Files;
 import java.util.Objects;
 
 import static java.lang.Math.ceil;
@@ -45,9 +48,11 @@ public class LiblouisBrailleTextRasterizer implements Rasterizer<BrailleText> {
             throw new RuntimeException(e);
         }
         try {
-            mTranslator = new Translator("src\\main\\resources\\mapping\\liblouis\\de-g0.utb");
+            GeneralResource table = new GeneralResource("/mapping/liblouis/de-g0.utb");
+            File tableFile = table.getFileOrExportResource();
+            mTranslator = new Translator(tableFile.getAbsolutePath());
         } catch (Exception e) {
-            throw new RuntimeException(e.getCause());
+            throw new RuntimeException("Error while creating liblouis translator:", e);
         }
     }