A lot of small updates. Finishing split-merge functions.

This commit is contained in:
Dmitry Isaenko 2020-01-24 23:44:21 +03:00
parent ca061cd1f2
commit 3d3fb56f9e
16 changed files with 416 additions and 266 deletions

View file

@ -3,6 +3,7 @@ package nsusbloader.COM.NET;
import javafx.concurrent.Task;
import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.ModelControllers.LogPrinter;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.NSLDataTypes.EMsgType;
import nsusbloader.COM.Helpers.NSSplitReader;
@ -42,7 +43,7 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
else
this.extras = "";
this.switchIP = switchIP;
this.logPrinter = new LogPrinter();
this.logPrinter = new LogPrinter(EModule.USB_NET_TRANSFERS);
this.nspMap = new HashMap<>();
this.nspFileSizes = new HashMap<>();
// Filter and remove empty/incorrect split-files

View file

@ -3,6 +3,7 @@ package nsusbloader.COM.USB;
import javafx.concurrent.Task;
import nsusbloader.ModelControllers.LogPrinter;
import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.NSLDataTypes.EMsgType;
import org.usb4java.*;
@ -34,7 +35,7 @@ public class UsbCommunications extends Task<Void> {
this.nspMap = new LinkedHashMap<>();
for (File f: nspList)
nspMap.put(f.getName(), f);
this.logPrinter = new LogPrinter();
this.logPrinter = new LogPrinter(EModule.USB_NET_TRANSFERS);
}
@Override

View file

@ -6,6 +6,7 @@ import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.stage.DirectoryChooser;
@ -14,6 +15,7 @@ import nsusbloader.AppPreferences;
import nsusbloader.COM.NET.NETCommunications;
import nsusbloader.COM.USB.UsbCommunications;
import nsusbloader.MediatorControl;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.ServiceWindow;
import java.io.File;
@ -25,6 +27,8 @@ import java.util.ResourceBundle;
public class FrontController implements Initializable {
@FXML
private Pane specialPane;
@FXML
private AnchorPane usbNetPane;
@FXML
private ChoiceBox<String> choiceProtocol, choiceNetUsb;
@ -35,7 +39,7 @@ public class FrontController implements Initializable {
@FXML
private Button switchThemeBtn;
@FXML
public NSTableViewController tableFilesListController; // Accessible from Mediator
public NSTableViewController tableFilesListController; // Accessible from Mediator (for drag-n-drop support)
@FXML
private Button selectNspBtn, selectSplitNspBtn, uploadStopBtn;
@ -167,7 +171,7 @@ public class FrontController implements Initializable {
}
/********************************************************************************************************************/
/*-****************************************************************************************************************-*/
/**
* Functionality for selecting NSP button.
* */
@ -290,30 +294,30 @@ public class FrontController implements Initializable {
* Called from mediator
* TODO: remove shitcoding practices
* */
public void notifyTransmissionStarted(boolean isTransmissionStarted){
if (isTransmissionStarted) {
public void notifyTransmThreadStarted(boolean isActive, EModule type){
if (! type.equals(EModule.USB_NET_TRANSFERS)){
usbNetPane.setDisable(isActive);
return;
}
if (isActive) {
selectNspBtn.setDisable(true);
selectSplitNspBtn.setDisable(true);
uploadStopBtn.setOnAction(e-> stopBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Stop"));
btnUpStopImage.getStyleClass().remove("regionUpload");
btnUpStopImage.getStyleClass().clear();
btnUpStopImage.getStyleClass().add("regionStop");
uploadStopBtn.setOnAction(e-> stopBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Stop"));
uploadStopBtn.getStyleClass().remove("buttonUp");
uploadStopBtn.getStyleClass().add("buttonStop");
return;
}
selectNspBtn.setDisable(false);
selectSplitNspBtn.setDisable(false);
uploadStopBtn.setOnAction(e-> uploadBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Upload"));
btnUpStopImage.getStyleClass().remove("regionStop");
btnUpStopImage.getStyleClass().clear();
btnUpStopImage.getStyleClass().add("regionUpload");
uploadStopBtn.setOnAction(e-> uploadBtnAction());
uploadStopBtn.setText(resourceBundle.getString("btn_Upload"));
uploadStopBtn.getStyleClass().remove("buttonStop");
uploadStopBtn.getStyleClass().add("buttonUp");
}

View file

@ -119,6 +119,10 @@ public class NSLMainController implements Initializable {
public FrontController getFrontCtrlr(){
return FrontTabController;
}
public SplitMergeController getSmCtrlr(){
return SplitMergeTabController;
}
/**
* Save preferences before exit
* */

View file

@ -3,15 +3,14 @@ package nsusbloader.Controllers;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.*;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import nsusbloader.AppPreferences;
import nsusbloader.MediatorControl;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.ServiceWindow;
import nsusbloader.Utilities.SplitMergeTool;
@ -22,6 +21,9 @@ import java.util.ResourceBundle;
public class SplitMergeController implements Initializable {
@FXML
private ToggleGroup splitMergeTogGrp;
@FXML
private VBox smToolPane;
@FXML
private RadioButton splitRad, mergeRad;
@FXML
@ -31,16 +33,23 @@ public class SplitMergeController implements Initializable {
@FXML
private Label fileFolderLabelLbl,
fileFolderActualPathLbl,
saveToPathLbl;
saveToPathLbl,
statusLbl;
private ResourceBundle resourceBundle;
private Region convertRegion;
private Task<Boolean> smTask;
private Thread smThread;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
convertRegion = new Region();
convertBtn.setGraphic(convertRegion);
splitRad.setOnAction((actionEvent -> {
statusLbl.setText("");
convertRegion.getStyleClass().clear();
convertRegion.getStyleClass().add("regionSplitToOne");
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_File"));
@ -49,6 +58,7 @@ public class SplitMergeController implements Initializable {
convertBtn.setDisable(true);
}));
mergeRad.setOnAction((actionEvent -> {
statusLbl.setText("");
convertRegion.getStyleClass().clear();
convertRegion.getStyleClass().add("regionOneToSplit");
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_Folder"));
@ -74,6 +84,7 @@ public class SplitMergeController implements Initializable {
}));
selectFileFolderBtn.setOnAction(actionEvent -> {
statusLbl.setText("");
if (splitRad.isSelected()) {
FileChooser fc = new FileChooser();
fc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
@ -102,51 +113,75 @@ public class SplitMergeController implements Initializable {
}
});
convertBtn.setOnAction(actionEvent -> {
if (MediatorControl.getInstance().getTransferActive()) {
ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"), resourceBundle.getString("windowBodyPleaseFinishTransfersFirst"));
return;
}
if (splitRad.isSelected()){
updateProcess(true);
Task<Void> task = SplitMergeTool.splitFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
task.setOnSucceeded(workerStateEvent -> this.updateProcess(false));
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
else{
updateProcess(true);
Task<Void> task = SplitMergeTool.mergeFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
task.setOnSucceeded(workerStateEvent -> this.updateProcess(false));
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
});
convertBtn.setOnAction(actionEvent -> setConvertBtnAction());
}
private void updateProcess(boolean isStart){
public void notifySmThreadStarted(boolean isStart, EModule type){
if (! type.equals(EModule.SPLIT_MERGE_TOOL)){
smToolPane.setDisable(isStart);
return;
}
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);
convertBtn.setOnAction(e -> stopBtnAction());
convertBtn.setText(resourceBundle.getString("btn_Stop"));
convertRegion.getStyleClass().clear();
convertRegion.getStyleClass().add("regionStop");
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);
convertBtn.setOnAction(e -> setConvertBtnAction());
convertBtn.setText(resourceBundle.getString("tabSplMrg_Btn_Convert"));
convertRegion.getStyleClass().clear();
if (splitRad.isSelected())
convertRegion.getStyleClass().add("regionSplitToOne");
else
convertRegion.getStyleClass().add("regionOneToSplit");
}
/**
* It's button listener when convert-process in progress
* */
private void stopBtnAction(){
if (smThread != null && smThread.isAlive())
smTask.cancel(false);
}
/**
* It's button listener when convert-process NOT in progress
* */
private void setConvertBtnAction(){
if (MediatorControl.getInstance().getTransferActive()) {
ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"), resourceBundle.getString("windowBodyPleaseFinishTransfersFirst"));
return;
}
if (splitRad.isSelected())
smTask = SplitMergeTool.splitFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
else
smTask = SplitMergeTool.mergeFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
smTask.setOnCancelled(event -> statusLbl.setText(resourceBundle.getString("failure_txt")));
smTask.setOnSucceeded(event -> {
if (smTask.getValue())
statusLbl.setText(resourceBundle.getString("done_txt"));
else
statusLbl.setText(resourceBundle.getString("failure_txt"));
});
smThread = new Thread(smTask);
smThread.setDaemon(true);
smThread.start();
}
/**
* Save application settings on exit
* */
public void updatePreferencesOnExit(){
if (splitRad.isSelected())
AppPreferences.getInstance().setSplitMergeType(0);

View file

@ -1,12 +1,13 @@
package nsusbloader;
import nsusbloader.Controllers.NSLMainController;
import nsusbloader.NSLDataTypes.EModule;
import java.util.concurrent.atomic.AtomicBoolean;
public class MediatorControl {
private AtomicBoolean isTransferActive = new AtomicBoolean(false); // Overcoded just for sure
private NSLMainController applicationController;
private NSLMainController mainCtrler;
public static MediatorControl getInstance(){
return MediatorControlHold.INSTANCE;
@ -16,13 +17,14 @@ public class MediatorControl {
private static final MediatorControl INSTANCE = new MediatorControl();
}
public void setController(NSLMainController controller){
this.applicationController = controller;
this.mainCtrler = controller;
}
public NSLMainController getContoller(){ return this.applicationController; }
public NSLMainController getContoller(){ return this.mainCtrler; }
public synchronized void setTransferActive(boolean state) {
isTransferActive.set(state);
applicationController.getFrontCtrlr().notifyTransmissionStarted(state);
public synchronized void setBgThreadActive(boolean isActive, EModule appModuleType) {
isTransferActive.set(isActive);
mainCtrler.getFrontCtrlr().notifyTransmThreadStarted(isActive, appModuleType);
mainCtrler.getSmCtrlr().notifySmThreadStarted(isActive, appModuleType);
}
public synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
}

View file

@ -1,6 +1,7 @@
package nsusbloader.ModelControllers;
import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.NSLDataTypes.EMsgType;
import java.io.File;
@ -14,11 +15,11 @@ public class LogPrinter {
private BlockingQueue<Double> progressQueue;
private HashMap<String, EFileStatus> statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap
public LogPrinter(){
public LogPrinter(EModule whoIsAsking){
this.msgQueue = new LinkedBlockingQueue<>();
this.progressQueue = new LinkedBlockingQueue<>();
this.statusMap = new HashMap<>();
this.msgConsumer = new MessagesConsumer(this.msgQueue, this.progressQueue, this.statusMap);
this.msgConsumer = new MessagesConsumer(whoIsAsking, this.msgQueue, this.progressQueue, this.statusMap);
this.msgConsumer.start();
}
/**
@ -42,7 +43,8 @@ public class LogPrinter {
default:
msgQueue.put(message);
}
}catch (InterruptedException ie){
}
catch (InterruptedException ie){
ie.printStackTrace();
}
}

View file

@ -7,6 +7,7 @@ import javafx.scene.control.TextArea;
import nsusbloader.Controllers.NSTableViewController;
import nsusbloader.MediatorControl;
import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.NSLDataTypes.EModule;
import java.util.ArrayList;
import java.util.HashMap;
@ -20,10 +21,12 @@ public class MessagesConsumer extends AnimationTimer {
private final ProgressBar progressBar;
private final HashMap<String, EFileStatus> statusMap;
private final NSTableViewController tableViewController;
private final EModule appModuleType;
private boolean isInterrupted;
MessagesConsumer(BlockingQueue<String> msgQueue, BlockingQueue<Double> progressQueue, HashMap<String, EFileStatus> statusMap){
MessagesConsumer(EModule appModuleType, BlockingQueue<String> msgQueue, BlockingQueue<Double> progressQueue, HashMap<String, EFileStatus> statusMap){
this.appModuleType = appModuleType;
this.isInterrupted = false;
this.msgQueue = msgQueue;
@ -38,7 +41,7 @@ public class MessagesConsumer extends AnimationTimer {
progressBar.setProgress(0.0);
progressBar.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
MediatorControl.getInstance().setTransferActive(true);
MediatorControl.getInstance().setBgThreadActive(true, appModuleType);
}
@Override
@ -60,7 +63,7 @@ public class MessagesConsumer extends AnimationTimer {
}
if (isInterrupted) { // It's safe 'cuz it's could't be interrupted while HashMap populating
MediatorControl.getInstance().setTransferActive(false);
MediatorControl.getInstance().setBgThreadActive(false, appModuleType);
progressBar.setProgress(0.0);
if (statusMap.size() > 0)

View file

@ -0,0 +1,7 @@
package nsusbloader.NSLDataTypes;
public enum EModule {
USB_NET_TRANSFERS,
SPLIT_MERGE_TOOL,
RCM
}

View file

@ -2,205 +2,284 @@ package nsusbloader.Utilities;
import javafx.concurrent.Task;
import nsusbloader.ModelControllers.LogPrinter;
import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.NSLDataTypes.EMsgType;
import java.io.*;
import java.util.Arrays;
public class SplitMergeTool {
// TODO: ADD ABILITY TO INTERRUPT PROCESS
public static Task<Void> splitFile(String filePath, String saveToPath){
LogPrinter logPrinter = new LogPrinter();
return new Task<Void>() {
@Override
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));
BufferedOutputStream fragmentBos;
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++){
fragmentBos = new BufferedOutputStream(
new FileOutputStream(new File(folder.getAbsolutePath()+File.separator+String.format("%02d", i)))
);
counter = 0;
while (counter < 1024){ // 0xffff0000 total
chunk = new byte[4194240];
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);
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 Task<Boolean> splitFile(String filePath, String saveToPath){
return new SplitTask(filePath, saveToPath);
};
// 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 ?
public static Task<Void> mergeFile(String filePath, String saveToPath){
LogPrinter logPrinter = new LogPrinter();
return new Task<Void>() {
@Override
protected Void call() {
logPrinter.print("Merge file: "+filePath, EMsgType.INFO);
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;
}
};
public static Task<Boolean> mergeFile(String filePath, String saveToPath){
return new MergeTask(filePath, saveToPath);
}
}
class SplitTask extends Task<Boolean>{
private LogPrinter logPrinter;
private String saveToPath;
private String filePath;
SplitTask(String filePath, String saveToPath){
this.filePath = filePath;
this.saveToPath = saveToPath;
logPrinter = new LogPrinter(EModule.SPLIT_MERGE_TOOL);
}
@Override
protected Boolean 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++){
if (this.isCancelled()){
logPrinter.print("Split task interrupted!", EMsgType.PASS);
logPrinter.close();
return false;
}
if (! folder.mkdir()){
if (folder.exists()){
if (i >= 50){
logPrinter.print("Can't create new file.", EMsgType.FAIL);
logPrinter.close();
return false;
}
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 false;
}
}
logPrinter.print("Save results to: "+folder.getAbsolutePath(), EMsgType.INFO);
break;
}
try{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream fragmentBos;
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++){
fragmentBos = new BufferedOutputStream(
new FileOutputStream(new File(folder.getAbsolutePath()+File.separator+String.format("%02d", i)))
);
counter = 0;
while (counter < 1024){ // 0xffff0000 total
if (this.isCancelled()){
fragmentBos.close();
bis.close();
boolean isDeleted = folder.delete();
File[] chArrToDel = folder.listFiles();
if (! isDeleted && chArrToDel != null){
isDeleted = true;
for (File chunkFile : chArrToDel)
isDeleted &= chunkFile.delete();
isDeleted &= folder.delete();
}
logPrinter.print("Split task interrupted and folder "+(isDeleted?"deleted.":"is not deleted."), EMsgType.PASS);
logPrinter.close();
return false;
}
chunk = new byte[4194240];
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);
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 false;
}
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 true;
}
}
class MergeTask extends Task<Boolean> {
private LogPrinter logPrinter;
private String saveToPath;
private String filePath;
MergeTask(String filePath, String saveToPath) {
this.filePath = filePath;
this.saveToPath = saveToPath;
logPrinter = new LogPrinter(EModule.SPLIT_MERGE_TOOL);
}
@Override
protected Boolean call() {
logPrinter.print("Merge file: "+filePath, EMsgType.INFO);
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 false;
}
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());
//*******
for (int i = 0; ; i++){
if (this.isCancelled()){
logPrinter.print("Split task interrupted!", EMsgType.PASS);
logPrinter.close();
return false;
}
if (resultFile.exists()){
if (i >= 50){
logPrinter.print("Can't create new file.", EMsgType.FAIL);
logPrinter.close();
return false;
}
logPrinter.print("Trying to create a good new file...", EMsgType.WARNING);
resultFile = new File(saveToPath+File.separator+"!_"+i+"_"+folder.getName());
continue;
}
logPrinter.print("Save results to: "+resultFile.getAbsolutePath(), EMsgType.INFO);
break;
}
//*******
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){
if (this.isCancelled()){
bos.close();
bis.close();
boolean isDeleted = resultFile.delete();
logPrinter.print("Split task interrupted and file "+(isDeleted?"deleted.":"is not deleted."), EMsgType.PASS);
logPrinter.close();
return false;
}
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);
return false;
}
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 true;
}
}