diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..5e7e021
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4584532
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+/bin/
+/lib/
+/src/main/resources/*
\ No newline at end of file
diff --git a/.project b/.project
new file mode 100644
index 0000000..fd458f2
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ FileHasher
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3a21537
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..eaef085
--- /dev/null
+++ b/README.md
@@ -0,0 +1,20 @@
+# File-Hasher
+A Program for mass-checking the SHA-512 Hash of whole Subdirectories.
+
+## How to use
+Go to the [Releases-Tab](../../releases) and download the attached JAR-File. Put the file into a folder wherever you want but **don't let them in the Downloads Folder** since all Output Files will be created in that folder.
+
+## Pictures
+Here some pictures that you know how the GUI looks like:
+
+### Program
+![Menu on Start](img/menu_start.png)
+![Ready to Go](img/menu_ready.png)
+![Request Done](img/menu_done.png)
+
+### Icon
+![Icon in the Task-Bar](img/icon-taskbar.png)
+
+## FAQ
+- Q: How to use it?
+ A: Read the text above. ;)
\ No newline at end of file
diff --git a/img/icon-taskbar.png b/img/icon-taskbar.png
new file mode 100644
index 0000000..cc0be87
Binary files /dev/null and b/img/icon-taskbar.png differ
diff --git a/img/menu_done.png b/img/menu_done.png
new file mode 100644
index 0000000..6ac77fb
Binary files /dev/null and b/img/menu_done.png differ
diff --git a/img/menu_ready.png b/img/menu_ready.png
new file mode 100644
index 0000000..d3e61b5
Binary files /dev/null and b/img/menu_ready.png differ
diff --git a/img/menu_start.png b/img/menu_start.png
new file mode 100644
index 0000000..44e7880
Binary files /dev/null and b/img/menu_start.png differ
diff --git a/src/main/java/tk/dmanstrator/filehasher/Hasher.java b/src/main/java/tk/dmanstrator/filehasher/Hasher.java
new file mode 100644
index 0000000..55410eb
--- /dev/null
+++ b/src/main/java/tk/dmanstrator/filehasher/Hasher.java
@@ -0,0 +1,175 @@
+package tk.dmanstrator.filehasher;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.commons.io.FileUtils;
+
+/**
+ * Generates SHA-512 Hashes. Works for all files of a given Folder or for a given File.
+ *
+ * @author DManstrator
+ *
+ */
+public class Hasher {
+
+ /**
+ * Encoding for the File in case a filename or the Directory has Umlauts.
+ */
+ private static final String ENCODING = "UTF-8";
+
+ /**
+ * Hashing Method. Creates an Output File and returns the Path to it.
+ *
+ * @param mainFolderName
+ * Folder to hash
+ * @throws IllegalArgumentException
+ * When the Path is not a folder
+ * @throws FileNotFoundException
+ * When the Output File couldn't be created
+ * @throws UnsupportedEncodingException
+ * When the Encoding for the Output File is Unsupported
+ */
+ public String hash(String mainFolderName) throws IllegalArgumentException, FileNotFoundException, UnsupportedEncodingException {
+ File mainPath = new File(mainFolderName);
+ if (!mainPath.isDirectory()) {
+ throw new IllegalArgumentException(String.format("Given Folder '%s' is not a folder, re-check that!", mainFolderName));
+ }
+
+ Map filesWithHashes = getHashesOfFiles(mainFolderName);
+
+ String tmpFolderName = getFolderName(mainFolderName); // tmp for using folderName in Stream#map
+ String folderName = tmpFolderName != null ? tmpFolderName : "null";
+
+ StringBuilder builder = new StringBuilder("Path to scan: " + mainFolderName + System.lineSeparator());
+ String hashes = filesWithHashes.entrySet().stream()
+ .map(entry -> String.format("%s: %s", entry.getKey().getPath().substring(mainFolderName.length() - folderName.length()),
+ entry.getValue()))
+ .collect(Collectors.joining(System.lineSeparator()));
+
+ String output = builder.append(hashes).toString();
+
+ String dateTime = getDateTime();
+ File outputFile = new File(String.format("%s-Hashes_%s.txt", folderName, dateTime));
+ try {
+ PrintWriter writer = new PrintWriter(outputFile.getName(), ENCODING);
+ writer.write(output);
+ writer.flush();
+ writer.close();
+ } catch (FileNotFoundException e) {
+ throw new FileNotFoundException(String.format("An error occured while creating the output file '%s', "
+ + "make sure the program has the rights to do so!", outputFile.getAbsolutePath()));
+ } catch (UnsupportedEncodingException e) {
+ throw new UnsupportedEncodingException(String.format("An error occured because '%s' is an Unsupported Encoding!", ENCODING));
+ }
+ return outputFile.getAbsolutePath();
+ }
+
+ /**
+ * Computes a SHA-512 Hash for every file of the given folder path.
+ *
+ * @param mainFolderName
+ * Path to the starting Directory
+ * @return a Map with the File as the Key and the SHA-512 Hash as the Value
+ */
+ public Map getHashesOfFiles(String mainFolderName) {
+ return getHashesOfFiles(new File(mainFolderName));
+ }
+
+ /**
+ * Computes a SHA-512 Hash for every file of the given folder path.
+ *
+ * @param mainFolder
+ * Path as File to the starting Directory
+ * @return a Map with the File as the Key and the SHA-512 Hash as the Value
+ */
+ public Map getHashesOfFiles(File mainFolder) {
+ if (!mainFolder.isDirectory()) {
+ return new HashMap<>();
+ }
+ Collection listFiles = FileUtils.listFiles(mainFolder, null, true);
+ return listFiles.stream().collect(Collectors.toMap(p -> p, p -> getHashOfFile(p)));
+ }
+
+ /**
+ * Generates a SHA-512 Hash of a File.
+ *
+ * @param filename
+ * Name of the File to get the Hash from
+ * @return a SHA-512 Hash of given File or null
if something
+ * went wrong
+ */
+ public String getHashOfFile(String filename) {
+ return getHashOfFile(new File(filename));
+ }
+
+ /**
+ * Generates a SHA-512 Hash of a File.
+ *
+ * @param file
+ * File to get the Hash from
+ * @return a SHA-512 Hash of given File or null
if something
+ * went wrong
+ * @see https://stackoverflow.com/a/33085670
+ */
+ public String getHashOfFile(File file) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-512");
+ byte[] digest = md.digest(Files.readAllBytes(Paths.get(file.getAbsolutePath())));
+ StringBuilder sb = new StringBuilder();
+ for(int i=0; i< digest.length; i++){
+ sb.append(Integer.toString((digest[i] & 0xff) + 0x100, 16).substring(1));
+ }
+ return sb.toString();
+ } catch (NoSuchAlgorithmException | IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Gets the deepest Folder Name from a given Path.
+ *
+ * @param mainFolderName
+ * Main Folder Name
+ * @return the deepest Folder Name from a given Path or null
if
+ * no folder could be retrieved from the given Folder Name.
+ */
+ private String getFolderName(String mainFolderName) {
+ int lastIndex = mainFolderName.lastIndexOf('/');
+ if (lastIndex == -1) { // Maybe Windows
+ int lastIndexWindows = mainFolderName.lastIndexOf('\\');
+ if (lastIndexWindows != -1) {
+ lastIndex = lastIndexWindows;
+ } else {
+ return null; // No slashes at all
+ }
+ }
+ return mainFolderName.substring(lastIndex + 1, mainFolderName.length());
+ }
+
+ /**
+ * Gets the current Time in Format yyyy-MM-dd_HH-mm-ss
.
+ *
+ * @return the current Time as a readable String
+ */
+ private String getDateTime() {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(System.currentTimeMillis());
+ return new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(cal.getTime()).toString();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/tk/dmanstrator/filehasher/Main.java b/src/main/java/tk/dmanstrator/filehasher/Main.java
new file mode 100644
index 0000000..d349565
--- /dev/null
+++ b/src/main/java/tk/dmanstrator/filehasher/Main.java
@@ -0,0 +1,210 @@
+package tk.dmanstrator.filehasher;
+
+import java.awt.Desktop;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import javafx.application.Application;
+import javafx.geometry.Insets;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.image.Image;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import javafx.stage.DirectoryChooser;
+import javafx.stage.Stage;
+
+/**
+ * Main File with GUI Support to execute the File Hasher.
+ *
+ * @author DManstrator
+ *
+ */
+public class Main extends Application {
+
+ /**
+ * Starts the GUI.
+ */
+ @Override
+ public void start(Stage primaryStage) throws Exception {
+ final DirectoryChooser directoryChooser = new DirectoryChooser();
+ configuringDirectoryChooser(directoryChooser);
+
+ // Creating a GridPane container
+ GridPane grid = new GridPane();
+ grid.setVgap(5);
+ grid.setHgap(5);
+
+ final Label pathLabel = new Label();
+ final Label pathNameLabel = new Label("Path:");
+ pathNameLabel.setMinWidth(30);
+
+ GridPane.setConstraints(pathNameLabel, 0, 0);
+ GridPane.setConstraints(pathLabel, 1, 0);
+
+ grid.getChildren().addAll(pathNameLabel, pathLabel);
+
+ Button chooseButton = new Button("Choose A Path");
+ Button okayButton = new Button("Okay");
+ Button closeButton = new Button("Exit");
+
+ chooseButton.setOnAction(action -> {
+ File dir = directoryChooser.showDialog(primaryStage);
+ if (dir != null) {
+ pathLabel.setText(dir.getAbsolutePath());
+ okayButton.setDisable(false);
+ } else {
+ pathLabel.setText(null);
+ okayButton.setDisable(true);
+ }
+ });
+
+ okayButton.setDisable(true);
+
+ closeButton.setOnAction(action -> {
+ primaryStage.close();
+ });
+
+ HBox buttons = new HBox();
+ buttons.setSpacing(5);
+ buttons.getChildren().addAll(chooseButton, okayButton, closeButton);
+
+ VBox root = new VBox();
+ root.setPadding(new Insets(10));
+ root.setSpacing(5);
+
+ root.getChildren().addAll(grid, buttons);
+
+ Scene scene = new Scene(root);
+
+ Image icon = new Image(getClass().getClassLoader().getResourceAsStream("img/logo.png"));
+ primaryStage.setTitle("File-Hasher");
+ primaryStage.setScene(scene);
+ primaryStage.getIcons().add(icon);
+ primaryStage.setMinWidth(270);
+ primaryStage.setMinHeight(115);
+ primaryStage.show();
+
+ okayButton.setOnAction(action -> {
+ Hasher hasher = new Hasher();
+
+ Button gotoButton = new Button("Open Folder");
+ Button returnButton = new Button("Return");
+
+ String pathToOutputFile = null;
+ String returnValue;
+ try {
+ pathToOutputFile = hasher.hash(pathLabel.getText());
+ returnValue = String.format("Successfully created %s as the Output File!", pathToOutputFile);
+ } catch (IllegalArgumentException | FileNotFoundException | UnsupportedEncodingException e) {
+ returnValue = e.getMessage();
+ gotoButton.setDisable(true);
+ }
+
+ Label userInformation = new Label(returnValue);
+ userInformation.setWrapText(true);
+
+ final String outputPath = pathToOutputFile;
+ gotoButton.setOnAction(gotoAction -> {
+ String error = openFolderWithFile(outputPath);
+ if (error != null) {
+ userInformation.setText(userInformation.getText() + System.lineSeparator() + error);
+ gotoButton.setDisable(true);
+ }
+ });
+
+ returnButton.setOnAction(returnAction -> {
+ buttons.getChildren().add(closeButton); // Disappears if not re-added
+ pathLabel.setText(null);
+ okayButton.setDisable(true);
+ primaryStage.setScene(scene);
+ });
+
+ HBox newButtons = new HBox();
+ newButtons.setSpacing(5);
+ newButtons.getChildren().addAll(gotoButton, returnButton, closeButton);
+
+ VBox out = new VBox();
+ out.setPadding(new Insets(10));
+ out.setSpacing(5);
+ out.getChildren().addAll(userInformation, newButtons);
+ out.setMinSize(500, 250);
+
+ Scene infoScreen = new Scene(out);
+ primaryStage.setScene(infoScreen);
+ primaryStage.setHeight(100); // trick to use min width
+
+ System.out.println(returnValue);
+ });
+ }
+
+ /**
+ * Opens the Folder to the given File.
+ *
+ * @param outputFile
+ * File to get Folder from
+ * @return null
if the call was successfully, else an Error Response
+ */
+ private static String openFolderWithFile(String outputFile) {
+ File testFile = new File(outputFile);
+ if (!testFile.isFile()) {
+ return "The file isn't avaliable (anymore)!";
+ }
+ try {
+ // new ProcessBuilder("explorer.exe", "/select,\"" + outputPath + "\"").start(); // doesn't work
+ Runtime.getRuntime().exec("explorer.exe /select," + outputFile);
+ } catch (IOException e) {
+ String currentDir = System.getProperty("user.dir");
+ try {
+ Desktop.getDesktop().open(new File(currentDir));
+ } catch (IOException e1) {
+ return "An Error occured: Cannot open the Folder for you!";
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Configures a Title and an initial Directory for a given Directory Chooser.
+ *
+ * @param directoryChooser
+ * Directory Chooser to change things on
+ */
+ private void configuringDirectoryChooser(DirectoryChooser directoryChooser) {
+ directoryChooser.setTitle("Choose a Directory to Scan");
+ directoryChooser.setInitialDirectory(new File(System.getProperty("user.home")));
+ }
+
+ /**
+ * Main Method. Checks for Program Arguments, if none given the GUI will be started.
+ *
+ * @param args
+ * Program Arguments
+ */
+ public static void main(String[] args) {
+ if (args.length != 0) {
+ Hasher hasher = new Hasher();
+ try {
+ String pathToOutputFile = hasher.hash(args[0]);
+ String output = String.format("Successfully created %s as the Output File!", pathToOutputFile);
+ System.out.println(output);
+ String error = openFolderWithFile(pathToOutputFile);
+ if (error != null) {
+ System.err.println(error);
+ }
+ System.exit(0);
+ } catch (IllegalArgumentException | FileNotFoundException | UnsupportedEncodingException e) {
+ System.err.println(e.getMessage());
+ System.exit(-1);
+ }
+ }
+
+ Application.launch(args);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/tk/dmanstrator/filehasher/package-info.java b/src/main/java/tk/dmanstrator/filehasher/package-info.java
new file mode 100644
index 0000000..cfc3c99
--- /dev/null
+++ b/src/main/java/tk/dmanstrator/filehasher/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * Main Package.
+ *
+ * @author DManstrator
+ *
+ */
+package tk.dmanstrator.filehasher;
\ No newline at end of file
diff --git a/src/test/java/tk/dmanstrator/filehasher/HasherTest.java b/src/test/java/tk/dmanstrator/filehasher/HasherTest.java
new file mode 100644
index 0000000..075ff8c
--- /dev/null
+++ b/src/test/java/tk/dmanstrator/filehasher/HasherTest.java
@@ -0,0 +1,140 @@
+package tk.dmanstrator.filehasher;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import tk.dmanstrator.filehasher.Hasher;
+
+/**
+ * Test Class for testing the Hasher. Used the following websites to compare the Hashes:
+ * https://emn178.github.io/online-tools/sha512_file_hash.html
+ * https://hash.online-convert.com/sha512-generator
+ *
+ * @author DManstrator
+ *
+ */
+public class HasherTest {
+
+ /**
+ * Map with Filepaths and SHA-512 Hashes to compare.
+ */
+ private final static Map HASHES = new HashMap() {
+ private static final long serialVersionUID = 5636217836120806223L;
+ {
+ put("src\\test\\resources\\folder1\\Testfile.txt",
+ "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8");
+ put("src\\test\\resources\\folder1\\Another-Testfile.txt",
+ "f11a72665f07e477918c6c8cef29f30942ea7d4ac7dd15bb61b0f6d52e284c4b31978d3238878994a30b7ddcf22cb4ffdad82cb407ecd418a92d0ce78c1a49dc");
+ put("src\\test\\resources\\folder2\\Test File.txt",
+ "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8");
+ put("src\\test\\resources\\folder2\\Testfile with Ümläuts.txt",
+ "c966988e7254a05ae05bb921a2955899dc47c209120b26faf96a6701cd884b258a3eb6bd5c035ed4e3e3865a84719332a05c458dad2da655a46ca29fa6d2dbc9");
+ }
+ };
+
+ /**
+ * Tests if the IllegalArgumentException is successfully thrown.
+ *
+ * @throws IllegalArgumentException
+ * @throws FileNotFoundException
+ * @throws UnsupportedEncodingException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testHashingFoldersNotValidPath() throws IllegalArgumentException, FileNotFoundException, UnsupportedEncodingException {
+ Hasher hasher = new Hasher();
+ hasher.hash("not/valid/path");
+ }
+
+ /**
+ * Tests if the program works normally and creates an output file. Also used "Windows Slashes" (Backslashes).
+ *
+ * @throws IllegalArgumentException
+ * @throws FileNotFoundException
+ * @throws UnsupportedEncodingException
+ */
+ @Test
+ public void testHashingFoldersRun() throws IllegalArgumentException, FileNotFoundException, UnsupportedEncodingException {
+ Hasher hasher = new Hasher();
+ String hash = hasher.hash("src\\test\\resources\\folder1");
+ Assert.assertNotNull(hash);
+ }
+
+ /**
+ * Tests if the SHA-512 Hashes are successfully computed.
+ */
+ @Test
+ public void testHashingFoldersNormal() {
+ Hasher hasher = new Hasher();
+ Map hashesOfFiles = hasher.getHashesOfFiles("src/test/resources/folder1");
+ for (Map.Entry entry : hashesOfFiles.entrySet()) {
+ boolean found = false;
+ for (Map.Entry hashEntry : HASHES.entrySet()) {
+ if (entry.getKey().equals(new File(hashEntry.getKey()))) {
+ found = true;
+ Assert.assertEquals(entry.getValue(), hashEntry.getValue());
+ break;
+ }
+ }
+ Assert.assertTrue(found);
+ }
+ }
+
+ /**
+ * Tests if the SHA-512 Hashes are successfully computed even there are Umlauts in the File Names.
+ */
+ @Test
+ public void testHashingFoldersAdvanced() {
+ Hasher hasher = new Hasher();
+ Map hashesOfFiles = hasher.getHashesOfFiles("src/test/resources/folder2");
+ for (Map.Entry entry : hashesOfFiles.entrySet()) {
+ boolean found = false;
+ for (Map.Entry hashEntry : HASHES.entrySet()) {
+ if (entry.getKey().equals(new File(hashEntry.getKey()))) {
+ found = true;
+ Assert.assertEquals(entry.getValue(), hashEntry.getValue());
+ break;
+ }
+ }
+ Assert.assertTrue(found);
+ }
+ }
+
+ /**
+ * Checks if the hash of a normal file gets successfully computed.
+ */
+ @Test
+ public void testHashingFileNormal() {
+ Hasher hasher = new Hasher();
+ String hashOfFile = hasher.getHashOfFile("src/test/resources/folder1/Testfile.txt");
+ Assert.assertEquals("861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8",
+ hashOfFile);
+ }
+
+ /**
+ * Checks if the hash of a file with Umlauts in the name gets successfully computed.
+ */
+ @Test
+ public void testHashingFileAdvanced() {
+ Hasher hasher = new Hasher();
+ String hashOfFile = hasher.getHashOfFile("src/test/resources/folder2/Testfile with Ümläuts.txt");
+ Assert.assertEquals("c966988e7254a05ae05bb921a2955899dc47c209120b26faf96a6701cd884b258a3eb6bd5c035ed4e3e3865a84719332a05c458dad2da655a46ca29fa6d2dbc9",
+ hashOfFile);
+ }
+
+ /**
+ * Checks if an invalid folder path returns an empty map.
+ */
+ @Test
+ public void testEmptyMap() {
+ Hasher hasher = new Hasher();
+ Map hashesOfFiles = hasher.getHashesOfFiles("not/valid/path");
+ Assert.assertTrue(hashesOfFiles.isEmpty());
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/folder1/Another-Testfile.txt b/src/test/resources/folder1/Another-Testfile.txt
new file mode 100644
index 0000000..32f411c
--- /dev/null
+++ b/src/test/resources/folder1/Another-Testfile.txt
@@ -0,0 +1 @@
+Another one!
\ No newline at end of file
diff --git a/src/test/resources/folder1/Testfile.txt b/src/test/resources/folder1/Testfile.txt
new file mode 100644
index 0000000..c57eff5
--- /dev/null
+++ b/src/test/resources/folder1/Testfile.txt
@@ -0,0 +1 @@
+Hello World!
\ No newline at end of file
diff --git a/src/test/resources/folder2/Test File.txt b/src/test/resources/folder2/Test File.txt
new file mode 100644
index 0000000..c57eff5
--- /dev/null
+++ b/src/test/resources/folder2/Test File.txt
@@ -0,0 +1 @@
+Hello World!
\ No newline at end of file
diff --git "a/src/test/resources/folder2/Testfile with \303\234ml\303\244uts.txt" "b/src/test/resources/folder2/Testfile with \303\234ml\303\244uts.txt"
new file mode 100644
index 0000000..8f80d0c
--- /dev/null
+++ "b/src/test/resources/folder2/Testfile with \303\234ml\303\244uts.txt"
@@ -0,0 +1 @@
+Just in case..
\ No newline at end of file