diff --git a/src/main/java/nsusbloader/Controllers/SplitMergeController.java b/src/main/java/nsusbloader/Controllers/SplitMergeController.java index 30990cd..4d9cae5 100644 --- a/src/main/java/nsusbloader/Controllers/SplitMergeController.java +++ b/src/main/java/nsusbloader/Controllers/SplitMergeController.java @@ -1,5 +1,6 @@ package nsusbloader.Controllers; +import javafx.concurrent.Task; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; @@ -106,25 +107,52 @@ public class SplitMergeController implements Initializable { ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"), resourceBundle.getString("windowBodyPleaseFinishTransfersFirst")); return; } - MediatorControl.getInstance().setTransferActive(true); - /* + if (splitRad.isSelected()){ - SplitMergeTool.splitFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText()); - System.out.println("split"); + updateProcess(true); + Task task = SplitMergeTool.splitFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText()); + task.setOnSucceeded(workerStateEvent -> this.updateProcess(false)); + Thread thread = new Thread(task); + thread.setDaemon(true); + thread.start(); } else{ - System.out.println("merge"); - SplitMergeTool.mergeFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText()); + updateProcess(true); + Task task = SplitMergeTool.mergeFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText()); + task.setOnSucceeded(workerStateEvent -> this.updateProcess(false)); + Thread thread = new Thread(task); + thread.setDaemon(true); + thread.start(); } - */ + }); } + private void updateProcess(boolean isStart){ + if (isStart){ + MediatorControl.getInstance().getContoller().logArea.clear(); + MediatorControl.getInstance().setTransferActive(true); // TODO: remove & rewrite to interrupt function + convertBtn.setDisable(true);// TODO: remove & rewrite to interrupt function + splitRad.setDisable(true); + mergeRad.setDisable(true); + selectFileFolderBtn.setDisable(true); + changeSaveToBtn.setDisable(true); + return; + } + MediatorControl.getInstance().setTransferActive(false); + convertBtn.setDisable(false);// TODO: remove & rewrite to interrupt function + splitRad.setDisable(false); + mergeRad.setDisable(false); + selectFileFolderBtn.setDisable(false); + changeSaveToBtn.setDisable(false); + } + public void updatePreferencesOnExit(){ if (splitRad.isSelected()) AppPreferences.getInstance().setSplitMergeType(0); else AppPreferences.getInstance().setSplitMergeType(1); + AppPreferences.getInstance().setSplitMergeRecent(saveToPathLbl.getText()); } } \ No newline at end of file diff --git a/src/main/java/nsusbloader/Utilities/SplitMergeTool.java b/src/main/java/nsusbloader/Utilities/SplitMergeTool.java index 510ad4b..3053fc9 100644 --- a/src/main/java/nsusbloader/Utilities/SplitMergeTool.java +++ b/src/main/java/nsusbloader/Utilities/SplitMergeTool.java @@ -1,23 +1,42 @@ package nsusbloader.Utilities; +import javafx.concurrent.Task; +import nsusbloader.ModelControllers.LogPrinter; +import nsusbloader.NSLDataTypes.EMsgType; + import java.io.*; +import java.util.Arrays; public class SplitMergeTool { + // TODO: ADD ABILITY TO INTERRUPT PROCESS - public static Runnable splitFile(String filePath, String saveToPath){ - File file = new File(filePath); - File folder = new File(saveToPath+File.separator+"!_"+file.getName()); - - if (! folder.mkdir()){ // TODO: PROMPT - remove directory? - if (folder.exists()) - ;// folder exists - return - else - ;// folder not created and not exists - return - } - - return new Runnable() { + public static Task splitFile(String filePath, String saveToPath){ + LogPrinter logPrinter = new LogPrinter(); + return new Task() { @Override - public void run() { + protected Void call() { + File file = new File(filePath); + File folder = new File(saveToPath+File.separator+"!_"+file.getName()); + + logPrinter.print("Split file: "+filePath, EMsgType.INFO); + + for (int i = 0; i < 50; i++){ + if (! folder.mkdir()){ + if (folder.exists()){ + logPrinter.print("Trying to create a good new folder...", EMsgType.WARNING); + folder = new File(saveToPath+File.separator+"!_"+i+"_"+file.getName()); + continue; + } + else { // folder not created and not exists - return + logPrinter.print("Folder "+folder.getAbsolutePath()+" could not be created. Not enough rights or something like that?", EMsgType.FAIL); + logPrinter.close(); + return null; + } + } + logPrinter.print("Save results to: "+folder.getAbsolutePath(), EMsgType.INFO); + break; + } + try{ BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); @@ -25,7 +44,13 @@ public class SplitMergeTool { long counter; + long originalFileLen = file.length(); + + double chunkPercent = (4194240.0 / (originalFileLen / 100.0) / 100.0); + long totalSizeCnt = 0; + byte[] chunk; + int readBytesCnt; main_loop: for (int i = 0; ; i++){ @@ -35,52 +60,148 @@ public class SplitMergeTool { counter = 0; - while (counter < 512){ // 0xffff0000 total - chunk = new byte[8388480]; + while (counter < 1024){ // 0xffff0000 total + chunk = new byte[4194240]; - if (bis.read(chunk) < 0){ + if ((readBytesCnt = bis.read(chunk)) < 4194240){ + if (readBytesCnt > 0) + fragmentBos.write(chunk, 0, readBytesCnt); fragmentBos.close(); + logPrinter.updateProgress(1.0); break main_loop; } fragmentBos.write(chunk); - counter++; + logPrinter.updateProgress(chunkPercent * totalSizeCnt); + counter++; // NOTE: here we have some redundancy of variables. It has to be fixed one day. + totalSizeCnt++; } fragmentBos.close(); } bis.close(); + + //=============== let's check what we have ============== + logPrinter.print("Original file size: "+originalFileLen, EMsgType.INFO); + long totalChunksSize = 0; + File[] chunkFileArr = folder.listFiles(); + + if (chunkFileArr == null) { + logPrinter.print("Unable to check results. It means that something went wrong.", EMsgType.FAIL); + return null; + } + else { + Arrays.sort(chunkFileArr); + for (File chunkFile : chunkFileArr) { + logPrinter.print("Chunk " + chunkFile.getName() + " size: " + chunkFile.length(), EMsgType.INFO); + totalChunksSize += chunkFile.length(); + } + + logPrinter.print("Total chunks size: " + totalChunksSize, EMsgType.INFO); + + if (originalFileLen != totalChunksSize) + logPrinter.print("Sizes are different! Do NOT use this file for installations!", EMsgType.FAIL); + else + logPrinter.print("Sizes are the same! Split file should be good!", EMsgType.PASS); + } } catch (Exception e){ e.printStackTrace(); + logPrinter.print("Error: "+e.getMessage(), EMsgType.FAIL); } + logPrinter.print("Split task complete!", EMsgType.INFO); + logPrinter.close(); + + return null; } }; }; - public static Runnable mergeFile(String filePath, String saveToPath){ - File folder = new File(filePath); - File resultFile = new File(saveToPath+File.separator+"!_"+folder.getName()); - //BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(resultFile)); + // TODO: CHECK IF FILE WE'RE ABOUT TO CREATE IS EXISTS !!! + // TODO: not here: Add RECENT on current session level selection of the 'Select file/select folder' ? Already done ? - for (File sss : folder.listFiles(new FilenameFilter() { + public static Task mergeFile(String filePath, String saveToPath){ + LogPrinter logPrinter = new LogPrinter(); + + return new Task() { @Override - public boolean accept(File file, String s) { - System.out.println(s); - return false; - } - })){ - System.out.println("|"); - } + protected Void call() { + logPrinter.print("Merge file: "+filePath, EMsgType.INFO); - Runnable runnable = new Runnable() { - @Override - public void run() { + File folder = new File(filePath); + long cnkTotalSize = 0; + + File[] chunkFiles = folder.listFiles((file, s) -> s.matches("^[0-9][0-9]$")); + + if (chunkFiles == null){ + logPrinter.print("Selected folder doesn't have any chunks. Nothing to do here.", EMsgType.FAIL); + logPrinter.close(); + return null; + } + + Arrays.sort(chunkFiles); + + logPrinter.print("Next files will be merged in following order: ", EMsgType.INFO); + for (File cnk : chunkFiles){ + logPrinter.print(" "+cnk.getName(), EMsgType.INFO); + cnkTotalSize += cnk.length(); + } + + double chunkPercent = (4194240.0 / (cnkTotalSize / 100.0) / 100.0); + long totalSizeCnt = 0; + + File resultFile = new File(saveToPath+File.separator+"!_"+folder.getName()); + + logPrinter.print("Save results to: "+resultFile.getAbsolutePath(), EMsgType.INFO); + try { + BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(resultFile)); + + BufferedInputStream bis; + byte[] chunk; + int readBytesCnt; + + for (File cnk : chunkFiles){ + bis = new BufferedInputStream(new FileInputStream(cnk)); + while (true){ + chunk = new byte[4194240]; + readBytesCnt = bis.read(chunk); + + logPrinter.updateProgress(chunkPercent * totalSizeCnt); + totalSizeCnt++; + + if (readBytesCnt < 4194240){ + if (readBytesCnt > 0) + bos.write(chunk, 0, readBytesCnt); + break; + } + + bos.write(chunk); + } + bis.close(); + } + bos.close(); + + //=============== let's check what we have ============== + long resultFileSize = resultFile.length(); + logPrinter.print("Total chunks size: " + cnkTotalSize, EMsgType.INFO); + logPrinter.print("Merged file size: " + resultFileSize, EMsgType.INFO); + + if (cnkTotalSize != resultFileSize) + logPrinter.print("Sizes are different! Do NOT use this file for installations!", EMsgType.FAIL); + else + logPrinter.print("Sizes are the same! Split file should be good!", EMsgType.PASS); + } + catch (Exception e){ + e.printStackTrace(); + logPrinter.print("Error: "+e.getMessage(), EMsgType.FAIL); + } + + logPrinter.print("Merge task complete!", EMsgType.INFO); + logPrinter.close(); + return null; } }; - - return runnable; } }