From af97eb2bc8dd5eb747d3c4ae891baa0b523cf80c Mon Sep 17 00:00:00 2001 From: Caleb Fontenot Date: Mon, 13 Nov 2023 09:20:57 -0600 Subject: [PATCH] Work on this assignment is going so freaking slow --- .../.~lock.mp5-binary-files-1.odt# | 1 - .../Exercise17_01.txt | Bin 0 -> 400 bytes .../Printed HTMLs/AddressBookFX.html | 286 +++++++ .../Printed HTMLs/CombineFilesFX.html | 160 ++++ .../Printed HTMLs/Exercise17_01.html | 80 ++ .../Printed HTMLs/Exercise17_03.html | 94 +++ .../Printed HTMLs/Exercise17_05.html | 107 +++ .../Printed HTMLs/HexEditorFX.html | 177 +++++ .../Printed HTMLs/SplitFilesFX.html | 152 ++++ .../nbproject/build-impl.xml | 88 ++- .../nbproject/genfiles.properties | 6 +- .../nbproject/project.properties | 6 +- .../nbproject/project.xml | 1 + .../files_calebfontenot/CombineFilesFX.java | 78 +- .../mp5/files_calebfontenot/HexEditorFX.java | 147 ++++ .../mp5/files_calebfontenot/SplitFilesFX.java | 31 +- .../mp6_calebfontenot/PriorityQueueASDV.java | 695 +++++++++--------- .../ZIPs/MP5-Binary-Files_CalebFontenot.zip | Bin 636823 -> 655948 bytes 18 files changed, 1713 insertions(+), 396 deletions(-) delete mode 100644 Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/.~lock.mp5-binary-files-1.odt# create mode 100644 Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Exercise17_01.txt create mode 100644 Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/AddressBookFX.html create mode 100644 Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/CombineFilesFX.html create mode 100644 Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_01.html create mode 100644 Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_03.html create mode 100644 Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_05.html create mode 100644 Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/HexEditorFX.html create mode 100644 Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/SplitFilesFX.html create mode 100644 Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/HexEditorFX.java diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/.~lock.mp5-binary-files-1.odt# b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/.~lock.mp5-binary-files-1.odt# deleted file mode 100644 index dfab56d..0000000 --- a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/.~lock.mp5-binary-files-1.odt# +++ /dev/null @@ -1 +0,0 @@ -,caleb,caleb-gaming-laptop-archlinux,20.10.2023 21:26,file:///home/caleb/.config/libreoffice/4; \ No newline at end of file diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Exercise17_01.txt b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Exercise17_01.txt new file mode 100644 index 0000000000000000000000000000000000000000..8cfb7e4a80da7c014e43ab731ae95cbb6a6aff4c GIT binary patch literal 400 zcmYk%TMolO2t!fYrmy{PIGie1>W9UQu?@`3Yi2$d?pytD7x2$T{IT!H;=9nR((uvI z@ay}(7y7uetF+!AmzEFT?6UdIqfu$pb|_QjsmDjlXU6|t_M@w(2D&nO>&cVTO?l(G Rxts9qWDk8@J~QyY`%ax`0ulfK literal 0 HcmV?d00001 diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/AddressBookFX.html b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/AddressBookFX.html new file mode 100644 index 0000000..2a835f7 --- /dev/null +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/AddressBookFX.html @@ -0,0 +1,286 @@ + + + +AddressBookFX.java + + + + +
/home/caleb/ASDV-Java/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/AddressBookFX.java
+
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
+ */
+package com.calebfontenot.mp5.files_calebfontenot;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import javafx.application.Application;
+import javafx.geometry.HPos;
+import javafx.geometry.Pos;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.ColumnConstraints;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.RowConstraints;
+import javafx.stage.Stage;
+
+/**
+ *
+ * @author caleb
+ */
+public class AddressBookFX extends Application {
+
+    static File addressBook = new File("AddressBookFX.dat");
+    static int addressArrayPointer = 0;
+    static ArrayList<AddressBookEntry> addressArray = new ArrayList<>();
+    static TextField nameTextField = new TextField();
+    static TextField streetTextField = new TextField();
+    static TextField cityTextField = new TextField();
+    static TextField stateTextField = new TextField();
+    static TextField zipTextField = new TextField();
+    static Label addressBookCounter = new Label("Items in address book:");
+    static Label indexLabel = new Label();
+
+    @Override
+    public void start(Stage stage) throws Exception
+    {
+        getData();
+        BorderPane primaryBorderPane = new BorderPane();
+        GridPane textFieldGridPane = new GridPane();
+        GridPane addressFieldPane = new GridPane();
+        GridPane buttonFieldPane = new GridPane();
+
+        // Text fields / labels
+        textFieldGridPane.add(new Label("Name"), 0, 0);
+        textFieldGridPane.add(new Label("Street"), 0, 1);
+        textFieldGridPane.add(new Label("City"), 0, 2);
+        addressFieldPane.add(new Label("State"), 2, 0);
+        addressFieldPane.add(new Label("ZIP"), 4, 0);
+        textFieldGridPane.add(nameTextField, 1, 0);
+        textFieldGridPane.add(streetTextField, 1, 1);
+        textFieldGridPane.add(addressFieldPane, 1, 2);
+        addressFieldPane.add(cityTextField, 1, 0);
+        addressFieldPane.add(stateTextField, 3, 0);
+        addressFieldPane.add(zipTextField, 5, 0);
+        textFieldGridPane.getColumnConstraints().add(new ColumnConstraints(50));
+        primaryBorderPane.setTop(textFieldGridPane);
+
+        // Buttons
+        Button addButton = new Button("Add");
+        Button firstButton = new Button("First");
+        Button nextButton = new Button("Next");
+        Button previousButton = new Button("Previous");
+        Button lastButton = new Button("Last");
+        Button updateButton = new Button("Update");
+        buttonFieldPane.add(indexLabel, 0, 0);
+        buttonFieldPane.add(addButton, 1, 0);
+        buttonFieldPane.add(firstButton, 2, 0);
+        buttonFieldPane.add(nextButton, 3, 0);
+        buttonFieldPane.add(previousButton, 4, 0);
+        buttonFieldPane.add(lastButton, 5, 0);
+        buttonFieldPane.add(updateButton, 6, 0);
+        buttonFieldPane.add(addressBookCounter, 7, 0);
+
+        primaryBorderPane.setBottom(buttonFieldPane);
+        buttonFieldPane.setAlignment(Pos.CENTER);
+        buttonFieldPane.setHgap(10);
+
+        addButton.setOnAction(e -> {
+            addressArray.add(new AddressBookEntry());
+            updateData();
+        });
+        firstButton.setOnAction(e -> {
+            addressArrayPointer = 0;
+            getEntry(addressArrayPointer);
+        });
+        nextButton.setOnAction(e -> {
+            if (addressArrayPointer >= addressArray.size() - 1) {
+                addressArrayPointer = 0;
+            } else {
+                addressArrayPointer++;
+            }
+            getEntry(addressArrayPointer);
+        });
+        previousButton.setOnAction(e -> {
+            if (addressArrayPointer > 0) {
+                addressArrayPointer--;
+            } else {
+                addressArrayPointer = addressArray.size() - 1;
+            }
+            getEntry(addressArrayPointer);
+        });
+        lastButton.setOnAction(e -> {
+            addressArrayPointer = addressArray.size() - 1;
+            getEntry(addressArrayPointer);
+        });
+        updateButton.setOnAction(e -> {
+            AddressBookEntry entry = addressArray.get(addressArrayPointer);
+            entry.setName(nameTextField.getText());
+            entry.setCity(nameTextField.getText());
+            entry.setStreet(streetTextField.getText());
+            entry.setCity(cityTextField.getText());
+            entry.setState(stateTextField.getText());
+            entry.setZip(zipTextField.getText());
+            updateData();
+        });
+
+        // init fields with data from first entry
+        getEntry(0);
+
+        Scene scene = new Scene(primaryBorderPane);
+        stage.setScene(scene);
+        stage.show();
+    }
+
+    public static AddressBookEntry getEntry(int index)
+    {
+        AddressBookEntry entry = addressArray.get(index);
+        indexLabel.setText("Current index: " + index);
+        addressBookCounter.setText("Items in address book: " + addressArray.size());
+        nameTextField.setText(entry.getName());
+        streetTextField.setText(entry.getStreet());
+        cityTextField.setText(entry.getCity());
+        stateTextField.setText(entry.getState());
+        zipTextField.setText(entry.getZip());
+        return entry;
+    }
+
+    public static void updateData()
+    {
+        try (ObjectOutputStream fileStream = new ObjectOutputStream(new FileOutputStream(addressBook))) {
+            fileStream.writeObject(addressArray);
+        } catch (IOException ex) {
+            System.out.println(ex);
+        }
+    }
+
+    public static void getData()
+    {
+        if (!addressBook.exists()) {
+            addressArray.add(new AddressBookEntry());
+            updateData();
+        } else {
+            try (ObjectInputStream fileStream = new ObjectInputStream(new FileInputStream(addressBook))) {
+                addressArray = (ArrayList<AddressBookEntry>) fileStream.readObject();
+            } catch (IOException ex) {
+                System.out.println(ex);
+            } catch (ClassNotFoundException ex) {
+                System.out.println(ex);
+            }
+        }
+    }
+
+    public static void main(String[] args)
+    {
+        launch();
+    }
+}
+
+class AddressBookEntry implements Serializable {
+
+    private String name;
+    private String street;
+    private String city;
+    private String state;
+    private String zip;
+
+    public AddressBookEntry()
+    {
+        this.name = "Enter a name here.";
+        this.street = "Enter a street here.";
+        this.city = "Enter a city here.";
+        this.state = "Enter a state here.";
+        this.zip = "Enter a zip here.";
+    }
+
+    public AddressBookEntry(String name, String street, String city, String state, String zip)
+    {
+        this.name = name;
+        this.street = street;
+        this.city = city;
+        this.state = state;
+        this.zip = zip;
+    }
+
+    public String getZip()
+    {
+        return zip;
+    }
+
+    public void setZip(String zip)
+    {
+        this.zip = zip;
+    }
+
+    public String getState()
+    {
+        return state;
+    }
+
+    public void setState(String state)
+    {
+        this.state = state;
+    }
+
+    public String getCity()
+    {
+        return city;
+    }
+
+    public void setCity(String city)
+    {
+        this.city = city;
+    }
+
+    public String getStreet()
+    {
+        return street;
+    }
+
+    public void setStreet(String street)
+    {
+        this.street = street;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+}
+
+
+ diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/CombineFilesFX.html b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/CombineFilesFX.html new file mode 100644 index 0000000..b6afb2e --- /dev/null +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/CombineFilesFX.html @@ -0,0 +1,160 @@ + + + +CombineFilesFX.java + + + + +
/home/caleb/ASDV-Java/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/CombineFilesFX.java
+
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
+ */
+package com.calebfontenot.mp5.files_calebfontenot;
+
+import java.io.DataInput;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javafx.application.Application;
+import javafx.geometry.Pos;
+import javafx.scene.Scene;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Alert.AlertType;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.GridPane;
+import javafx.stage.FileChooser;
+import javafx.stage.Stage;
+
+/**
+ *
+ * @author caleb
+ */
+public class CombineFilesFX extends Application {
+
+    static ArrayList<File> files = new ArrayList<File>();
+    final FileChooser fileChooser = new FileChooser();
+
+    @Override
+    public void start(final Stage stage) throws Exception {
+        fileChooser.setTitle("Open File to Split...");
+        BorderPane primaryBorderPane = new BorderPane();
+        GridPane textFieldGridPane = new GridPane();
+
+        Label infoLabel = new Label("Point me at the files that were output by SplitFilesFX.java.");
+        Label chooseFile = new Label("Choose files to combine: ");
+        Button openFilePicker = new Button("Choose...");
+        Button run = new Button("Start");
+        textFieldGridPane.add(chooseFile, 0, 0);
+        textFieldGridPane.add(openFilePicker, 1, 0);
+        primaryBorderPane.setAlignment(run, Pos.CENTER);
+
+        primaryBorderPane.setTop(infoLabel);
+        primaryBorderPane.setCenter(textFieldGridPane);
+        primaryBorderPane.setBottom(run);
+
+        openFilePicker.setOnAction(e -> {
+            // When we initially get the files from the file chooser, it returns an unsortable list. Because of this, we need to create a new List with its data.
+            files.addAll(fileChooser.showOpenMultipleDialog(openFilePicker.getScene().getWindow()));
+            // The file picker appears to return files in a random order, so we need to sort them by file name.
+            Collections.sort(files, new Comparator<File>() {
+                public int compare(File o1, File o2) {
+                    return extractInt(o1.getName()) - extractInt(o2.getName());
+                }
+
+                String findMatch(String s) {
+                    Pattern findNum = Pattern.compile("\\d+$");
+                    Matcher match = findNum.matcher(s);
+                    while (match.find()) {
+                        return match.group();
+                    }
+                    return "";
+                }
+
+                int extractInt(String s) {
+                    String num = findMatch(s);
+                    System.out.println(num);
+                    // return 0 if no digits found
+                    return num.isEmpty() ? 0 : Integer.parseInt(num);
+                }
+            });
+        });
+
+        run.setOnAction(e -> {
+            if (files == null) {
+                e.consume();
+            }
+            combineFiles(files);
+        });
+
+        Scene scene = new Scene(primaryBorderPane);
+        stage.setScene(scene);
+        stage.show();
+    }
+
+    public static void combineFiles(List<File> filesToCombine) {
+        String outputPath = filesToCombine.get(0).getParent();
+        try (FileOutputStream dataOut = new FileOutputStream(outputPath + "/" + "reconstructed_" + filesToCombine.get(0).getName().substring(0, (filesToCombine.get(0).getName().length() - 2)))) {
+            System.out.println("Writing to " + outputPath + "/" + "reconstructed_" + filesToCombine.get(0).getName().substring(0, (filesToCombine.get(0).getName().length() - 2)));
+            for (File file : filesToCombine) {
+                try (FileInputStream dataIn = new FileInputStream(file)) {
+                    System.out.println("Opening the source file " + file.getName() + "!");
+                    byte[] buffer = new byte[4096];
+                    int bytesRead = -1;
+
+                    while ((bytesRead = dataIn.read(buffer)) != -1) {
+                        dataOut.write(buffer, 0, bytesRead);
+                    }
+                }
+            catch (IOException ex) {
+            System.out.println(ex);
+        }
+            }
+        } catch (IOException ex) {
+            System.out.println(ex);
+        }
+            Alert alert = new Alert(AlertType.INFORMATION);
+            alert.setTitle("Success!");
+            alert.setContentText("Successfully combined the files!");
+
+            alert.showAndWait();
+        }
+
+    
+
+    public static void main(String[] args) {
+        launch();
+    }
+}
+
+
+ diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_01.html b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_01.html new file mode 100644 index 0000000..b7c7b78 --- /dev/null +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_01.html @@ -0,0 +1,80 @@ + + + +Exercise17_01.java + + + + +
/home/caleb/ASDV-Java/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/Exercise17_01.java
+
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
+ */
+package com.calebfontenot.mp5.files_calebfontenot;
+
+import java.io.EOFException;
+import java.io.FileNotFoundException;
+import java.io.RandomAccessFile;
+
+/**
+ *
+ * @author caleb
+ */
+public class Exercise17_01 {
+
+    public static void main(String[] args)
+    {
+        try (RandomAccessFile fileIO = new RandomAccessFile("Exercise17_01.txt", "rw")) {
+            int random = 0;
+            System.out.println("Writing data to file...");
+            for (int i = 1; i < 100 + 1; ++i) {
+                random = (int) (Math.random() * 9) + 1;
+                System.out.print(random + " ");
+                if (i != 0 && i % 10 == 0) {
+                    System.out.println();
+                }
+                fileIO.writeInt(random);
+            }
+            System.out.println("Wrote to the file successfully!");
+            System.out.println("File contents:");
+            fileIO.seek(0);
+            int readIterator = 1;
+            while (true) {
+                try {
+                    System.out.print(fileIO.readInt() + " ");
+                    if (readIterator != 0 && readIterator % 10 == 0) {
+                        System.out.println();
+                    }
+                    ++readIterator;
+                } catch (EOFException e) {
+                    break;
+                }
+
+            }
+
+        } catch (Exception ex) {
+            System.out.println(ex);
+        }
+
+    }
+}
+
+
+ diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_03.html b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_03.html new file mode 100644 index 0000000..396259c --- /dev/null +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_03.html @@ -0,0 +1,94 @@ + + + +Exercise17_03.java + + + + +
/home/caleb/ASDV-Java/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/Exercise17_03.java
+
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
+ */
+package com.calebfontenot.mp5.files_calebfontenot;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ *
+ * @author caleb
+ */
+public class Exercise17_03 {
+
+    static int fileSize = Math.abs((int) (Math.random() * 1024));
+
+    public static void writeData()
+    {
+        try (FileOutputStream fileWrite = new FileOutputStream("Exercise17_03.dat")) {
+            // Write a unspecified number of integers into the file.
+            // Must be positive!
+            int randInt = 0;
+            for (int i = 0; i < fileSize; ++i) {
+                randInt = (int) (Math.random() * 10);
+                fileWrite.write(randInt);
+            }
+        } catch (IOException ex) {
+            System.out.println(ex);
+        }
+        System.out.println("Wrote data to the file!");
+    }
+
+    public static int[] readData()
+    {
+        int[] fileData = new int[fileSize];
+        try (FileInputStream fileRead = new FileInputStream("Exercise17_03.dat")) {
+            // Read the data back
+            int dataIterator = 0;
+            int dataStream = 0;
+            while (fileRead.available() > 0) {
+                dataStream = fileRead.read();
+                fileData[dataIterator++] = dataStream;
+                System.out.print(dataStream + " ");
+                if ((dataIterator + 1) % 10 == 0) {
+                    System.out.println();
+                }
+            }
+        } catch (IOException ex) {
+            System.out.println(ex);
+        }
+        return fileData;
+    }
+    
+    public static void main(String[] args)
+    {
+        System.out.println("Ints to write: " + fileSize);
+        writeData();
+        int[] fileData = readData();
+        // Sum the digits
+        int sum = 0;
+        for (int i: fileData) {
+         sum += i;   
+        }
+        System.out.println("\nThe sum of the integers in the file is: " + sum);
+    }
+}
+
+
+ diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_05.html b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_05.html new file mode 100644 index 0000000..afde774 --- /dev/null +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/Exercise17_05.html @@ -0,0 +1,107 @@ + + + +Exercise17_05.java + + + + +
/home/caleb/ASDV-Java/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/Exercise17_05.java
+
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
+ */
+package com.calebfontenot.mp5.files_calebfontenot;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.io.ObjectOutputStream;
+import java.util.Date;
+
+/**
+ *
+ * @author caleb
+ */
+public class Exercise17_05 {
+    public static void main(String[] args) {
+        File dataFile = new File("Exercise17_05.dat");
+        if(!dataFile.exists()) {
+            try (ObjectOutputStream fileStream = new ObjectOutputStream(new FileOutputStream(dataFile))) {
+                fileStream.writeObject(new DataContainer());
+            } catch (IOException ex) {
+                System.out.println(ex);
+            }
+        }
+        DataContainer data = null;
+        try (ObjectInputStream fileStream = new ObjectInputStream(new FileInputStream(dataFile))) {
+            data = (DataContainer) fileStream.readObject();
+        } catch (IOException ex) {
+                System.out.println(ex);
+            } catch (ClassNotFoundException ex) {
+                System.out.println(ex);
+            }
+        // Now print out the data!
+        System.out.println("We got the data from the file!");
+        System.out.println(data.toString());
+    }
+}
+
+class DataContainer  implements Serializable {
+    int[] intArray = {1, 2, 3, 4};
+    Date currentDate = new Date();
+    double doubleMoment = 5.5;
+
+    public int[] getIntArray()
+    {
+        return intArray;
+    }
+
+    public Date getCurrentDate()
+    {
+        return currentDate;
+    }
+
+    public double getDoubleMoment()
+    {
+        return doubleMoment;
+    }
+
+    @Override
+    public String toString()
+    {
+        String intString = "[";
+        for (int i = 0; i < intArray.length - 1; ++i) {
+            intString += intArray[i];
+            if (i == (intArray.length - 2)) {
+                intString += "]";
+            } else {
+                intString += ", ";
+            }
+        }
+        return "DataContainer{" + "intArray=" + intString + ", currentDate=" + currentDate + ", doubleMoment=" + doubleMoment + '}';
+    }
+}
+
+ diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/HexEditorFX.html b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/HexEditorFX.html new file mode 100644 index 0000000..0230190 --- /dev/null +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/HexEditorFX.html @@ -0,0 +1,177 @@ + + + +HexEditorFX.java + + + + +
/home/caleb/ASDV-Java/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/HexEditorFX.java
+
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
+ */
+package com.calebfontenot.mp5.files_calebfontenot;
+
+import static com.calebfontenot.mp5.files_calebfontenot.SplitFilesFX.alert;
+import static com.calebfontenot.mp5.files_calebfontenot.SplitFilesFX.file;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import javafx.application.Application;
+import javafx.geometry.Pos;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextArea;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.GridPane;
+import javafx.stage.FileChooser;
+import javafx.stage.Stage;
+
+/**
+ *
+ * @author caleb
+ */
+public class HexEditorFX extends Application {
+
+    final FileChooser fileChooser = new FileChooser();
+    static File file = null;
+
+    @Override
+    public void start(Stage stage) throws Exception {
+        Label label = new Label("Open a file...");
+        Button openFileButton = new Button("Choose...");
+        TextArea editorWindow = new TextArea();
+        Button saveFileButton = new Button("Save");
+
+        editorWindow.setWrapText(true);
+
+        BorderPane bp = new BorderPane();
+        GridPane openFileGridPane = new GridPane();
+
+        openFileGridPane.add(label, 0, 0);
+        openFileGridPane.add(openFileButton, 1, 0);
+
+        bp.setTop(openFileGridPane);
+        bp.setCenter(editorWindow);
+        bp.setBottom(saveFileButton);
+        bp.setAlignment(saveFileButton, Pos.CENTER);
+
+        openFileButton.setOnAction(e -> {
+            file = fileChooser.showOpenDialog(openFileButton.getScene().getWindow());
+            byte[] data = null;
+            System.out.println("Getting data from fileand encoding it as hex...");
+            try (FileInputStream dataIn = new FileInputStream(file)) {
+                data = dataIn.readAllBytes();
+            } catch (FileNotFoundException ex) {
+                ex.printStackTrace();
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+            String dataString = encodeHexString(data);
+            editorWindow.setText(dataString);
+        });
+
+        saveFileButton.setOnAction(e -> {
+            if (file == null) {
+                alert.setTitle("No file selected!");
+                alert.setHeaderText("No file selected!");
+                alert.setContentText("You have to open a file first, silly!");
+                alert.showAndWait();
+            }
+            System.out.println("Re-encoding hex back into a byte array...");
+
+            try (FileOutputStream dataOut = new FileOutputStream(file)) {
+                byte[] bytesToSave = decodeHexString(editorWindow.getText());
+                dataOut.write(bytesToSave);
+            } catch (FileNotFoundException ex) {
+                ex.printStackTrace();
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            } catch (IllegalArgumentException ex) {
+                alert.setTitle("Invalid Hex!");
+                alert.setContentText("Invalid hex entered into the text box, unable to save.");
+                alert.showAndWait();
+            }
+            alert.setTitle("Save successful!");
+            alert.setContentText("File saved successfully.");
+            alert.showAndWait();
+        });
+
+        Scene scene = new Scene(bp);
+        stage.setScene(scene);
+        stage.show();
+
+    }
+
+    private int toDigit(char hexChar) {
+        int digit = Character.digit(hexChar, 16);
+        if (digit == -1) {
+            throw new IllegalArgumentException(
+                    "Invalid Hexadecimal Character: " + hexChar);
+        }
+        return digit;
+    }
+
+    public byte hexToByte(String hexString) {
+        int firstDigit = toDigit(hexString.charAt(0));
+        int secondDigit = toDigit(hexString.charAt(1));
+        return (byte) ((firstDigit << 4) + secondDigit);
+    }
+
+    public byte[] decodeHexString(String hexString) {
+        if (hexString.length() % 2 == 1) {
+            throw new IllegalArgumentException(
+                    "Invalid hexadecimal String supplied.");
+        }
+        byte[] bytes = new byte[hexString.length() / 2];
+        for (int i = 0; i < hexString.length(); i += 2) {
+            bytes[i / 2] = hexToByte(hexString.substring(i, i + 2));
+        }
+        return bytes;
+    }
+
+    public String byteToHex(byte num) {
+        char[] hexDigits = new char[2];
+        hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16);
+        hexDigits[1] = Character.forDigit((num & 0xF), 16);
+        return new String(hexDigits);
+    }
+
+    public String encodeHexString(byte[] byteArray) {
+        StringBuffer hexStringBuffer = new StringBuffer();
+        for (int i = 0; i < byteArray.length; i++) {
+            hexStringBuffer.append(byteToHex(byteArray[i]));
+        }
+        return hexStringBuffer.toString();
+    }
+
+    public static void main(String[] args) {
+        launch(args);
+    }
+}
+
+
+ diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/SplitFilesFX.html b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/SplitFilesFX.html new file mode 100644 index 0000000..4320332 --- /dev/null +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/Printed HTMLs/SplitFilesFX.html @@ -0,0 +1,152 @@ + + + +SplitFilesFX.java + + + + +
/home/caleb/ASDV-Java/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/SplitFilesFX.java
+
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
+ */
+package com.calebfontenot.mp5.files_calebfontenot;
+
+import java.io.DataInput;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import javafx.application.Application;
+import javafx.geometry.Pos;
+import javafx.scene.Scene;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ProgressBar;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.GridPane;
+import javafx.stage.FileChooser;
+import javafx.stage.Stage;
+
+/**
+ *
+ * @author caleb
+ */
+public class SplitFilesFX extends Application {
+    static File file = null;
+    final  FileChooser fileChooser = new FileChooser();
+    static ProgressBar pb = new ProgressBar();
+    static Alert alert = new Alert(Alert.AlertType.INFORMATION);
+    @Override
+    public void start(final Stage stage) throws Exception
+    {
+        fileChooser.setTitle("Open File to Split...");
+        BorderPane primaryBorderPane = new BorderPane();
+        BorderPane secondaryBoarderPane = new BorderPane();
+        GridPane textFieldGridPane = new GridPane();
+        
+        pb.prefWidthProperty().bind(stage.widthProperty());
+
+        Label infoLabel = new Label("If you split a file named tmp into 3 smaller files,\n the three smaller files are temp.txt.1, temp.txt.2, and temp.txt.3. ");
+        Label chooseFile = new Label("Choose a file to split: ");
+        Button openFilePicker = new Button("Choose...");
+        Label splitCountLabel = new Label("Enter the amount of files to split into: ");
+        TextField splitCount = new TextField();
+        Button run = new Button("Start");
+        textFieldGridPane.add(chooseFile, 0, 0);
+        textFieldGridPane.add(openFilePicker, 1, 0);
+        textFieldGridPane.add(splitCountLabel, 0, 1);
+        textFieldGridPane.add(splitCount, 1, 1);
+        secondaryBoarderPane.setAlignment(run, Pos.CENTER);
+
+        primaryBorderPane.setTop(infoLabel);
+        primaryBorderPane.setCenter(textFieldGridPane);
+        
+        secondaryBoarderPane.setBottom(run);
+        secondaryBoarderPane.setTop(pb);
+        
+        primaryBorderPane.setBottom(secondaryBoarderPane);
+
+        openFilePicker.setOnAction(e -> {
+            file = fileChooser.showOpenDialog(openFilePicker.getScene().getWindow());
+        });
+
+        run.setOnAction(e -> {
+            if (file == null) {
+                e.consume();
+            }
+            splitFile(file, Integer.parseInt(splitCount.getText()));
+        });
+
+        Scene scene = new Scene(primaryBorderPane);
+        stage.setScene(scene);
+        stage.show();
+    }
+    
+    public static void splitFile(File fileToSplit, int splitCount) {
+        int outputFileSize = (int) fileToSplit.length() / splitCount;
+        System.out.println("output file size will be: " + outputFileSize);
+        if (outputFileSize < 0) {
+                    alert.setTitle("Output files too large");
+                    alert.setHeaderText("Output files too large");
+                    alert.setContentText("Please increase the amount of files to split!");
+
+                    alert.showAndWait();
+                    return;
+        }
+        
+        double progress = 0;
+        String outputPath = fileToSplit.getParent();
+        // Open the original file
+        try (FileInputStream dataIn = new FileInputStream(fileToSplit)) {
+            System.out.println("Opening the source file!");
+            for (int i = 0; i < splitCount; ++i) {
+                progress = (i * 100) / splitCount;
+                System.out.println(progress);
+                pb.setProgress(progress);
+                dataIn.mark(outputFileSize * (i + 1));
+                try (FileOutputStream dataOut = new FileOutputStream(outputPath + "/"  + fileToSplit.getName() + "." + (i + 1))) {
+                    dataOut.write(dataIn.readNBytes(outputFileSize), 0, outputFileSize);
+                    System.out.println("Writing to " + outputPath + "/" + fileToSplit.getName() + "." + (i + 1));
+                }
+            }
+            
+        } catch (IOException ex) {
+            System.out.println(ex);
+        }
+        
+    }
+    
+
+    public static void main(String[] args)
+    {
+        launch();
+    }
+}
+/*
+
+ */
+
+
+ diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/build-impl.xml b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/build-impl.xml index 22ab97e..fde7389 100644 --- a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/build-impl.xml +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/build-impl.xml @@ -119,7 +119,43 @@ is divided into following sections: - + + + + + + + + + + + + + + + + + + + + + + + + + + Must set platform.home + Must set platform.bootcp + Must set platform.java + Must set platform.javac + + The J2SE Platform is not correctly set up. + Your active platform is: ${platform.active}, but the corresponding property "platforms.${platform.active}.home" is not found in the project's properties files. + Either open the project in the IDE and setup the Platform with the same name or add it manually. + For example like this: + ant -Duser.properties.file=<path_to_property_file> jar (where you put the property "platforms.${platform.active}.home" in a .properties file) + or ant -Dplatforms.${platform.active}.home=<path_to_JDK_home> jar (where no properties file is used) + @@ -242,20 +278,6 @@ is divided into following sections: - - - - - - - - - - - - - - @@ -343,7 +365,7 @@ is divided into following sections: - + @@ -394,7 +416,7 @@ is divided into following sections: - + @@ -436,7 +458,7 @@ is divided into following sections: - + @@ -515,7 +537,7 @@ is divided into following sections: - + @@ -543,7 +565,7 @@ is divided into following sections: - + @@ -619,7 +641,7 @@ is divided into following sections: - + @@ -850,6 +872,9 @@ is divided into following sections: + + + @@ -899,7 +924,7 @@ is divided into following sections: - + @@ -933,7 +958,7 @@ is divided into following sections: - + @@ -965,7 +990,7 @@ is divided into following sections: - + @@ -1199,7 +1224,7 @@ is divided into following sections: To run this application from the command line without Ant, try: - java -jar "${dist.jar.resolved}" + ${platform.java} -jar "${dist.jar.resolved}" @@ -1301,8 +1326,8 @@ is divided into following sections: - - + + @@ -1495,16 +1520,19 @@ is divided into following sections: + + + - + - + - + diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/genfiles.properties b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/genfiles.properties index 5585d25..de9648f 100644 --- a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/genfiles.properties +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=a0844a83 +build.xml.data.CRC32=5b3e797d build.xml.script.CRC32=dee8d968 build.xml.stylesheet.CRC32=f85dc8f2@1.108.0.48 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=a0844a83 -nbproject/build-impl.xml.script.CRC32=025ed557 +nbproject/build-impl.xml.data.CRC32=5b3e797d +nbproject/build-impl.xml.script.CRC32=7cb0beee nbproject/build-impl.xml.stylesheet.CRC32=12e0a6c2@1.108.0.48 diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/project.properties b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/project.properties index ded35af..4ba8d76 100644 --- a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/project.properties +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/project.properties @@ -49,7 +49,7 @@ javac.compilerargs= javac.deprecation=false javac.external.vm=true javac.modulepath=\ - ${libs.JavaFX20.classpath} + ${libs.JavaFX_20.classpath} javac.processormodulepath= javac.processorpath=\ ${javac.classpath} @@ -101,7 +101,7 @@ manifest.custom.permissions= manifest.file=manifest.mf meta.inf.dir=${src.dir}/META-INF mkdist.disabled=false -platform.active=default_platform +platform.active=Graal_JDK_20 run.classpath=\ ${javac.classpath}:\ ${build.classes.dir}:\ @@ -109,7 +109,7 @@ run.classpath=\ # Space-separated list of JVM arguments used when running the project. # You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. # To set system properties for unit tests define test-sys-prop.name=value: -run.jvmargs=-XX:+UnlockExperimentalVMOptions -XX:+EagerJVMCI -XX:+EnableJVMCI -XX:+UseJVMCICompiler -XX:+UseJVMCINativeLibrary +run.jvmargs=--module-path=/usr/lib --add-modules javafx.controls -XX:+UnlockExperimentalVMOptions -XX:+EagerJVMCI -XX:+EnableJVMCI -XX:+UseJVMCICompiler -XX:+UseJVMCINativeLibrary run.modulepath=\ ${javac.modulepath} run.test.classpath=\ diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/project.xml b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/project.xml index 464cc39..f73fb1b 100644 --- a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/project.xml +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/nbproject/project.xml @@ -4,6 +4,7 @@ MP5-Binary-Files_CalebFontenot + diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/CombineFilesFX.java b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/CombineFilesFX.java index 4523d2b..b61b7c0 100644 --- a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/CombineFilesFX.java +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/CombineFilesFX.java @@ -10,10 +10,16 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javafx.application.Application; import javafx.geometry.Pos; import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; @@ -28,12 +34,11 @@ import javafx.stage.Stage; */ public class CombineFilesFX extends Application { - static List files = null; + static ArrayList files = new ArrayList(); final FileChooser fileChooser = new FileChooser(); @Override - public void start(final Stage stage) throws Exception - { + public void start(final Stage stage) throws Exception { fileChooser.setTitle("Open File to Split..."); BorderPane primaryBorderPane = new BorderPane(); GridPane textFieldGridPane = new GridPane(); @@ -51,7 +56,30 @@ public class CombineFilesFX extends Application { primaryBorderPane.setBottom(run); openFilePicker.setOnAction(e -> { - files = fileChooser.showOpenMultipleDialog(openFilePicker.getScene().getWindow()); + // When we initially get the files from the file chooser, it returns an unsortable list. Because of this, we need to create a new List with its data. + files.addAll(fileChooser.showOpenMultipleDialog(openFilePicker.getScene().getWindow())); + // The file picker appears to return files in a random order, so we need to sort them by file name. + Collections.sort(files, new Comparator() { + public int compare(File o1, File o2) { + return extractInt(o1.getName()) - extractInt(o2.getName()); + } + + String findMatch(String s) { + Pattern findNum = Pattern.compile("\\d+$"); + Matcher match = findNum.matcher(s); + while (match.find()) { + return match.group(); + } + return ""; + } + + int extractInt(String s) { + String num = findMatch(s); + System.out.println(num); + // return 0 if no digits found + return num.isEmpty() ? 0 : Integer.parseInt(num); + } + }); }); run.setOnAction(e -> { @@ -66,33 +94,37 @@ public class CombineFilesFX extends Application { stage.show(); } - public static void combineFiles(List filesToCombine) - { + public static void combineFiles(List filesToCombine) { String outputPath = filesToCombine.get(0).getParent(); - try (FileOutputStream dataOut = new FileOutputStream(outputPath + "/" + "reconstructed_" +filesToCombine.get(0).getName().substring( 0, (filesToCombine.get(0).getName().length() - 2)))) { - System.out.println("Writing to " + outputPath + "/" + "reconstructed_" +filesToCombine.get(0).getName().substring( 0, ( filesToCombine.get(0).getName().length() - 2))); + try (FileOutputStream dataOut = new FileOutputStream(outputPath + "/" + "reconstructed_" + filesToCombine.get(0).getName().substring(0, (filesToCombine.get(0).getName().length() - 2)))) { + System.out.println("Writing to " + outputPath + "/" + "reconstructed_" + filesToCombine.get(0).getName().substring(0, (filesToCombine.get(0).getName().length() - 2))); for (File file : filesToCombine) { try (FileInputStream dataIn = new FileInputStream(file)) { - System.out.println("Opening the source file!"); - byte[] buffer = new byte[4096]; // You can adjust the buffer size as needed + System.out.println("Opening the source file " + file.getName() + "!"); + byte[] buffer = new byte[4096]; + int bytesRead = -1; - int bytesRead; - while ((bytesRead = dataIn.read(buffer)) != -1) { - dataOut.write(buffer, 0, bytesRead); + while ((bytesRead = dataIn.read(buffer)) != -1) { + dataOut.write(buffer, 0, bytesRead); + } } - } + catch (IOException ex) { + System.out.println(ex); } - } catch (IOException ex) { - System.out.println(ex); - } - } + } + } catch (IOException ex) { + System.out.println(ex); + } + Alert alert = new Alert(AlertType.INFORMATION); + alert.setTitle("Success!"); + alert.setContentText("Successfully combined the files!"); + + alert.showAndWait(); + } + - public static void main(String[] args) - { + public static void main(String[] args) { launch(); } } -/* - - */ diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/HexEditorFX.java b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/HexEditorFX.java new file mode 100644 index 0000000..5b7946e --- /dev/null +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/HexEditorFX.java @@ -0,0 +1,147 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package com.calebfontenot.mp5.files_calebfontenot; + +import static com.calebfontenot.mp5.files_calebfontenot.SplitFilesFX.alert; +import static com.calebfontenot.mp5.files_calebfontenot.SplitFilesFX.file; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import javafx.application.Application; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.TextArea; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.GridPane; +import javafx.stage.FileChooser; +import javafx.stage.Stage; + +/** + * + * @author caleb + */ +public class HexEditorFX extends Application { + + final FileChooser fileChooser = new FileChooser(); + static File file = null; + + @Override + public void start(Stage stage) throws Exception { + Label label = new Label("Open a file..."); + Button openFileButton = new Button("Choose..."); + TextArea editorWindow = new TextArea(); + Button saveFileButton = new Button("Save"); + + editorWindow.setWrapText(true); + + BorderPane bp = new BorderPane(); + GridPane openFileGridPane = new GridPane(); + + openFileGridPane.add(label, 0, 0); + openFileGridPane.add(openFileButton, 1, 0); + + bp.setTop(openFileGridPane); + bp.setCenter(editorWindow); + bp.setBottom(saveFileButton); + bp.setAlignment(saveFileButton, Pos.CENTER); + + openFileButton.setOnAction(e -> { + file = fileChooser.showOpenDialog(openFileButton.getScene().getWindow()); + byte[] data = null; + System.out.println("Getting data from fileand encoding it as hex..."); + try (FileInputStream dataIn = new FileInputStream(file)) { + data = dataIn.readAllBytes(); + } catch (FileNotFoundException ex) { + ex.printStackTrace(); + } catch (IOException ex) { + ex.printStackTrace(); + } + String dataString = encodeHexString(data); + editorWindow.setText(dataString); + }); + + saveFileButton.setOnAction(e -> { + if (file == null) { + alert.setTitle("No file selected!"); + alert.setHeaderText("No file selected!"); + alert.setContentText("You have to open a file first, silly!"); + alert.showAndWait(); + } + System.out.println("Re-encoding hex back into a byte array..."); + + try (FileOutputStream dataOut = new FileOutputStream(file)) { + byte[] bytesToSave = decodeHexString(editorWindow.getText()); + dataOut.write(bytesToSave); + } catch (FileNotFoundException ex) { + ex.printStackTrace(); + } catch (IOException ex) { + ex.printStackTrace(); + } catch (IllegalArgumentException ex) { + alert.setTitle("Invalid Hex!"); + alert.setContentText("Invalid hex entered into the text box, unable to save."); + alert.showAndWait(); + } + alert.setTitle("Save successful!"); + alert.setContentText("File saved successfully."); + alert.showAndWait(); + }); + + Scene scene = new Scene(bp); + stage.setScene(scene); + stage.show(); + + } + + private int toDigit(char hexChar) { + int digit = Character.digit(hexChar, 16); + if (digit == -1) { + throw new IllegalArgumentException( + "Invalid Hexadecimal Character: " + hexChar); + } + return digit; + } + + public byte hexToByte(String hexString) { + int firstDigit = toDigit(hexString.charAt(0)); + int secondDigit = toDigit(hexString.charAt(1)); + return (byte) ((firstDigit << 4) + secondDigit); + } + + public byte[] decodeHexString(String hexString) { + if (hexString.length() % 2 == 1) { + throw new IllegalArgumentException( + "Invalid hexadecimal String supplied."); + } + byte[] bytes = new byte[hexString.length() / 2]; + for (int i = 0; i < hexString.length(); i += 2) { + bytes[i / 2] = hexToByte(hexString.substring(i, i + 2)); + } + return bytes; + } + + public String byteToHex(byte num) { + char[] hexDigits = new char[2]; + hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16); + hexDigits[1] = Character.forDigit((num & 0xF), 16); + return new String(hexDigits); + } + + public String encodeHexString(byte[] byteArray) { + StringBuffer hexStringBuffer = new StringBuffer(); + for (int i = 0; i < byteArray.length; i++) { + hexStringBuffer.append(byteToHex(byteArray[i])); + } + return hexStringBuffer.toString(); + } + + public static void main(String[] args) { + launch(args); + } +} diff --git a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/SplitFilesFX.java b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/SplitFilesFX.java index 0c79ce5..5e062af 100644 --- a/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/SplitFilesFX.java +++ b/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/SplitFilesFX.java @@ -12,8 +12,10 @@ import java.io.IOException; import javafx.application.Application; import javafx.geometry.Pos; import javafx.scene.Scene; +import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.Label; +import javafx.scene.control.ProgressBar; import javafx.scene.control.TextField; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; @@ -27,12 +29,17 @@ import javafx.stage.Stage; public class SplitFilesFX extends Application { static File file = null; final FileChooser fileChooser = new FileChooser(); + static ProgressBar pb = new ProgressBar(); + static Alert alert = new Alert(Alert.AlertType.INFORMATION); @Override public void start(final Stage stage) throws Exception { fileChooser.setTitle("Open File to Split..."); BorderPane primaryBorderPane = new BorderPane(); + BorderPane secondaryBoarderPane = new BorderPane(); GridPane textFieldGridPane = new GridPane(); + + pb.prefWidthProperty().bind(stage.widthProperty()); Label infoLabel = new Label("If you split a file named tmp into 3 smaller files,\n the three smaller files are temp.txt.1, temp.txt.2, and temp.txt.3. "); Label chooseFile = new Label("Choose a file to split: "); @@ -44,11 +51,15 @@ public class SplitFilesFX extends Application { textFieldGridPane.add(openFilePicker, 1, 0); textFieldGridPane.add(splitCountLabel, 0, 1); textFieldGridPane.add(splitCount, 1, 1); - primaryBorderPane.setAlignment(run, Pos.CENTER); + secondaryBoarderPane.setAlignment(run, Pos.CENTER); primaryBorderPane.setTop(infoLabel); primaryBorderPane.setCenter(textFieldGridPane); - primaryBorderPane.setBottom(run); + + secondaryBoarderPane.setBottom(run); + secondaryBoarderPane.setTop(pb); + + primaryBorderPane.setBottom(secondaryBoarderPane); openFilePicker.setOnAction(e -> { file = fileChooser.showOpenDialog(openFilePicker.getScene().getWindow()); @@ -68,12 +79,26 @@ public class SplitFilesFX extends Application { public static void splitFile(File fileToSplit, int splitCount) { int outputFileSize = (int) fileToSplit.length() / splitCount; + System.out.println("output file size will be: " + outputFileSize); + if (outputFileSize < 0) { + alert.setTitle("Output files too large"); + alert.setHeaderText("Output files too large"); + alert.setContentText("Please increase the amount of files to split!"); + + alert.showAndWait(); + return; + } + + double progress = 0; String outputPath = fileToSplit.getParent(); // Open the original file try (FileInputStream dataIn = new FileInputStream(fileToSplit)) { System.out.println("Opening the source file!"); for (int i = 0; i < splitCount; ++i) { - //dataIn.mark(outputFileSize * (i + 1)); + progress = (i * 100) / splitCount; + System.out.println(progress); + pb.setProgress(progress); + dataIn.mark(outputFileSize * (i + 1)); try (FileOutputStream dataOut = new FileOutputStream(outputPath + "/" + fileToSplit.getName() + "." + (i + 1))) { dataOut.write(dataIn.readNBytes(outputFileSize), 0, outputFileSize); System.out.println("Writing to " + outputPath + "/" + fileToSplit.getName() + "." + (i + 1)); diff --git a/Semester 3/Assignments/MP6_CalebFontenot/src/main/java/edu/slcc/asdv/caleb/mp6_calebfontenot/PriorityQueueASDV.java b/Semester 3/Assignments/MP6_CalebFontenot/src/main/java/edu/slcc/asdv/caleb/mp6_calebfontenot/PriorityQueueASDV.java index cf74ce0..fc7f90c 100644 --- a/Semester 3/Assignments/MP6_CalebFontenot/src/main/java/edu/slcc/asdv/caleb/mp6_calebfontenot/PriorityQueueASDV.java +++ b/Semester 3/Assignments/MP6_CalebFontenot/src/main/java/edu/slcc/asdv/caleb/mp6_calebfontenot/PriorityQueueASDV.java @@ -18,14 +18,12 @@ import java.util.Queue; import java.util.function.Consumer; public class PriorityQueueASDV> - implements Queue, Cloneable -{ + implements Queue, Cloneable { private Node head;//head private Node tail;//tail - class Node - { + class Node { E e; Node l; @@ -33,78 +31,56 @@ public class PriorityQueueASDV> } /** - * Inserts the specified element into this queue if it is possible to do so - * immediately without violating capacity restrictions, returning true upon - * success and throwing an IllegalStateException if no space is currently - * available. + * Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions, returning true upon success and throwing an IllegalStateException if no space is currently available. * * Specified by: add in interface Collection - * Parameters: e - the element to add Returns: true (as specified by - * Collection.add(E)) Throws: IllegalStateException - if the element cannot - * be added at this time due to capacity restrictions ClassCastException - - * if the class of the specified element prevents it from being added to - * this queue NullPointerException - if the specified element is null and - * this queue does not permit null elements IllegalArgumentException - if - * some property of this element prevents it from being added to this queue + * Parameters: e - the element to add Returns: true (as specified by Collection.add(E)) Throws: IllegalStateException - if the element cannot be added at this time due to capacity restrictions ClassCastException - if the class of the specified element prevents it from being added to this queue NullPointerException - if the specified element is null and this queue does not permit null elements IllegalArgumentException - if some property of this element prevents it from being added to this queue * * @param e - the element to add * @return true if this collection changed as a result of the call - * @throws IllegalStateException - if the element cannot be added at this - * time due to capacity restrictions + * @throws IllegalStateException - if the element cannot be added at this time due to capacity restrictions * @throws ClassCastException - if the class of the specified element - * @throws NullPointerException - if the specified element is null and this - * queue does not permit null elements - * @throws IllegalArgumentException - if some property of this element - * prevents it from being added to this queue + * @throws NullPointerException - if the specified element is null and this queue does not permit null elements + * @throws IllegalArgumentException - if some property of this element prevents it from being added to this queue */ @Override - public boolean add(E e) - { - if (e == null) - { + public boolean add(E e) { + if (e == null) { throw new NullPointerException("NULL elements not allowed!"); - } + } Node newNode = new Node(); newNode.e = e; //1. empty queue - if (this.head == null && this.tail == null) - { + if (this.head == null && this.tail == null) { this.head = this.tail = newNode; return true; - } + } int index = findCorrectPositionToInsertElement(e); //int index = findCorrectPositionToInsertElementHashCode(e); //2. we add at size ( last node) - if (index == size()) - { + if (index == size()) { tail.r = newNode;//1 newNode.l = tail;//2 tail = newNode;//3 - } - //3. we add at 0 in the front - else if (index == 0) - { + } //3. we add at 0 in the front + else if (index == 0) { newNode.r = head; this.head.l = newNode; this.head = newNode; - if (size() == 1) - { + if (size() == 1) { tail = head; - } - } - //4. we add in the middle - else - { + } + } //4. we add in the middle + else { Node p = head; - for (int i = 0; i < index - 1; ++i) - { + for (int i = 0; i < index - 1; ++i) { p = p.r; - } + } //after for loop p point one position before insertion newNode.l = p;//we connect the left of the new node @@ -120,181 +96,198 @@ public class PriorityQueueASDV> p.r.r.l = newNode;//we connect the left of the node AFTER the node //to be iserted to the new node - } + } return true; } @Override - public int size() - { + public int size() { Node p = this.head; int count = 0; - while (p != null) - { + while (p != null) { p = p.r; count++; - } + } return count; } - private int findCorrectPositionToInsertElement(E e) - { + private int findCorrectPositionToInsertElement(E e) { Node p = this.head; int pos = 0; - while (p != null) - { - if (e.compareTo(p.e) > 0) - { + while (p != null) { + if (e.compareTo(p.e) > 0) { p = p.r; ++pos; - } - else - { + } else { break; - } - } + } + } return pos; } - private int findCorrectPositionToInsertElementHashCode(E e) - { + private int findCorrectPositionToInsertElementHashCode(E e) { Node p = this.head; int pos = 0; - while (p != null) - { - if (e.hashCode() > p.e.hashCode()) - { + while (p != null) { + if (e.hashCode() > p.e.hashCode()) { p = p.r; ++pos; - } - else - { + } else { break; - } - } + } + } return pos; } /** - * Inserts the specified element into this queue if it is possible to do so - * immediately without violating capacity restrictions. When using a - * capacity-restricted queue, this method is generally preferable to add(E), - * which can fail to insert an element only by throwing an exception. + * Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions. When using a capacity-restricted queue, this method is generally preferable to add(E), which can fail to insert an element only by throwing an exception. * * @param e - the element to add - * @throws IllegalStateException - if the element cannot be added at this - * time due to capacity restrictions + * @throws IllegalStateException - if the element cannot be added at this time due to capacity restrictions * @throws ClassCastException - if the class of the specified element - * @throws NullPointerException - if the specified element is null and this - * queue does not permit null elements - * @throws IllegalArgumentException - if some property of this element - * prevents it from being added to this queue + * @throws NullPointerException - if the specified element is null and this queue does not permit null elements + * @throws IllegalArgumentException - if some property of this element prevents it from being added to this queue * @return true if the element was added */ @Override - public boolean offer(E e) - { + public boolean offer(E e) { return add(e); } + /** + * Retrieves and removes the head of this queue. This method differs from {@link #poll poll} only in that it throws an exception if this queue is empty. + * + *

+ * This implementation returns the result of {@code poll} unless the queue is empty. + * + * @return the head of this queue + * @throws NoSuchElementException if this queue is empty + */ @Override - public E remove() - { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + public E remove() { + Node pointer = head.r; + E removedElement = head.e; + head = head.r; + head.l = null; + + return removedElement; } /** - * Retrieves and removes the head of this queue, or returns null if this - * queue is empty. + * Retrieves and removes the head of this queue, or returns null if this queue is empty. * * Returns: the head of this queue, or null if this queue is empty * * @return */ @Override - public E poll() - { - if (size() == 0) - { + public E poll() { + if (size() == 0) { return null; - } - if (size() > 1) - { + } + if (size() > 1) { head = head.r; E e = head.l.e; head.l = null; return e; - } - else //size 1 - { + } else //size 1 + { E e = head.e; head = tail = null; return e; - } + } + } + /** + * Retrieves, but does not remove, the head of this queue. This method + * differs from {@link #peek peek} only in that it throws an exception + * if this queue is empty. + * + * @return the head of this queue + * @throws NoSuchElementException if this queue is empty + */ + @Override + public E element() { + if (head != null) { + return (E) head; + } else { + throw new NoSuchElementException("Element does not exist."); + } + } + /** + * Retrieves, but does not remove, the head of this queue, + * or returns {@code null} if this queue is empty. + * + * @return the head of this queue, or {@code null} if this queue is empty + */ + @Override + public E peek() { + return (E) head; } @Override - public E element() - { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - public E peek() - { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - public boolean isEmpty() - { + public boolean isEmpty() { return head == null && tail == null ? true : false; } - + /** + * Returns {@code true} if this collection contains the specified element. + * More formally, returns {@code true} if and only if this collection + * contains at least one element {@code e} such that + * {@code Objects.equals(o, e)}. + * + * @param o element whose presence in this collection is to be tested + * @return {@code true} if this collection contains the specified + * element + * @throws ClassCastException if the type of the specified element + * is incompatible with this collection + * ({@linkplain Collection##optional-restrictions optional}) + * @throws NullPointerException if the specified element is null and this + * collection does not permit null elements + * ({@linkplain Collection##optional-restrictions optional}) + */ @Override - public boolean contains(Object o) - { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + public boolean contains(Object o) { + Node pointer = head; + do { + if (pointer.equals(o)) { + return true; + } else { + pointer =pointer.r; + } + } while (pointer != null); + return false; } @Override - public Iterator iterator() - { - Iterator it = new Iterator() - { + public Iterator iterator() { + Iterator it = new Iterator() { Node p = head; @Override - public boolean hasNext() - { + public boolean hasNext() { return p == null ? false : true; } @Override - public E next() - { - if (hasNext() == false) - { + public E next() { + if (hasNext() == false) { throw new NoSuchElementException("the is no next element"); - } + } E e = p.e; p = p.r; return e; } @Override - public void forEachRemaining(Consumer action) - { - while (hasNext()) - { + public void forEachRemaining(Consumer action) { + while (hasNext()) { action.accept(p.e); p = p.r; - } + } } }; @@ -303,65 +296,111 @@ public class PriorityQueueASDV> } @Override - public Object[] toArray() - { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + public Object[] toArray() { + Node pointer = head; + Object[] returnArray = new Object[this.size()]; + int i = 0; + while (pointer.r != null) { + returnArray[i++] = pointer.e; + pointer = pointer.r; + } + returnArray[i++] = pointer.e; + return returnArray; } - + /** + * Returns an array containing all of the elements in this collection; + * the runtime type of the returned array is that of the specified array. + * If the collection fits in the specified array, it is returned therein. + * Otherwise, a new array is allocated with the runtime type of the + * specified array and the size of this collection. + * + *

If this collection fits in the specified array with room to spare + * (i.e., the array has more elements than this collection), the element + * in the array immediately following the end of the collection is set to + * {@code null}. (This is useful in determining the length of this + * collection only if the caller knows that this collection does + * not contain any {@code null} elements.) + * + *

If this collection makes any guarantees as to what order its elements + * are returned by its iterator, this method must return the elements in + * the same order. + * + * @apiNote + * This method acts as a bridge between array-based and collection-based APIs. + * It allows an existing array to be reused under certain circumstances. + * Use {@link #toArray()} to create an array whose runtime type is {@code Object[]}, + * or use {@link #toArray(IntFunction)} to control the runtime type of + * the array. + * + *

Suppose {@code x} is a collection known to contain only strings. + * The following code can be used to dump the collection into a previously + * allocated {@code String} array: + * + *

+     *     String[] y = new String[SIZE];
+     *     ...
+     *     y = x.toArray(y);
+ * + *

The return value is reassigned to the variable {@code y}, because a + * new array will be allocated and returned if the collection {@code x} has + * too many elements to fit into the existing array {@code y}. + * + *

Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. + * + * @param the component type of the array to contain the collection + * @param a the array into which the elements of this collection are to be + * stored, if it is big enough; otherwise, a new array of the same + * runtime type is allocated for this purpose. + * @return an array containing all of the elements in this collection + * @throws ArrayStoreException if the runtime type of any element in this + * collection is not assignable to the {@linkplain Class#getComponentType + * runtime component type} of the specified array + * @throws NullPointerException if the specified array is null + */ @Override - public T[] toArray(T[] a) - { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + public T[] toArray(T[] a) { + T[] genericArray = new T[this.size()]; + Node pointer = head; + for (int i = 0; i < this.size(); ++i) { + genericArray[i] = pointer; + } } /** - * Removes a single instance of the specified element from this collection, - * if it is present (optional operation). More formally, removes an element - * e such that (o==null ? e==null : o.equals(e)), if this collection - * contains one or more such elements. Returns true if this collection - * contained the specified element (or equivalently, if this collection - * changed as a result of the call). + * Removes a single instance of the specified element from this collection, if it is present (optional operation). More formally, removes an element e such that (o==null ? e==null : o.equals(e)), if this collection contains one or more such elements. Returns true if this collection contained the specified element (or equivalently, if this collection changed as a result of the call). * * @param o - element to be removed from this collection, if present - * @throws ClassCastException - if the type of the specified element is - * incompatible with this collection - * @throws NullPointerException - if the specified element is null and this - * collection does not permit null elements + * @throws ClassCastException - if the type of the specified element is incompatible with this collection + * @throws NullPointerException - if the specified element is null and this collection does not permit null elements * @return true if an element was removed as a result of this call */ @Override - public boolean remove(Object o) - { - if (o == null) - { + public boolean remove(Object o) { + if (o == null) { throw new NullPointerException("null vales not allowed"); - } - if (size() == 0) - { + } + if (size() == 0) { return false; - } + } Node p = this.head; int pos = 0; - while (p != this.tail) - { - if (p.e.equals(o)) - { - if (size() == 1) - { + while (p != this.tail) { + if (p.e.equals(o)) { + if (size() == 1) { this.head = this.tail = null; return true; - } + } this.removeAt(pos, (E) o); break; - } + } ++pos; p = p.r; - } - if (p == tail && p.e.equals(o)) - { + } + if (p == tail && p.e.equals(o)) { this.removeAt(size() - 1, (E) o); - } + } return true; } @@ -369,162 +408,141 @@ public class PriorityQueueASDV> * * @param pos * @param e - * @throws IndexOutOfBoundsException - if pos less 0 OR pos greater-equal - * size() + * @throws IndexOutOfBoundsException - if pos less 0 OR pos greater-equal size() * @return */ - private boolean removeAt(int pos, E e) - { - if (pos < 0 || pos >= size()) - { + private boolean removeAt(int pos, E e) { + if (pos < 0 || pos >= size()) { throw new IndexOutOfBoundsException(pos + " is out of bounds"); - } + } //1.list is empty - if (isEmpty()) - { + if (isEmpty()) { return false; - } - //2. one node exists - else if (size() == 1) - { + } //2. one node exists + else if (size() == 1) { this.head = this.tail = null; - } - //3. remove in the front( head) - else if (pos == 0) - { + } //3. remove in the front( head) + else if (pos == 0) { this.head = this.head.r; head.l = null; - } - //4. remove in the end ( tail) - else if (pos == size() - 1) - { + } //4. remove in the end ( tail) + else if (pos == size() - 1) { this.tail = this.tail.l; this.tail.r = null; - } - - //5. remove in the middle ( at least 3 nodes are in the queue) - else - { + } //5. remove in the middle ( at least 3 nodes are in the queue) + else { Node p = head; - for (int i = 0; i < pos - 1; ++i) - { + for (int i = 0; i < pos - 1; ++i) { p = p.r; - } + } p.r = p.r.r; p.r.l = p; - } + } return true; } - + /** + * Returns {@code true} if this collection contains all of the elements + * in the specified collection. + * + * @param c collection to be checked for containment in this collection + * @return {@code true} if this collection contains all of the elements + * in the specified collection + * @throws ClassCastException if the types of one or more elements + * in the specified collection are incompatible with this + * collection + * ({@linkplain Collection##optional-restrictions optional}) + * @throws NullPointerException if the specified collection contains one + * or more null elements and this collection does not permit null + * elements + * ({@linkplain Collection##optional-restrictions optional}) + * or if the specified collection is null. + * @see #contains(Object) + */ @Override - public boolean containsAll(Collection c) - { + public boolean containsAll(Collection c) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } /** - * Adds all of the elements in the specified collection to this collection - * (optional operation). The behavior of this operation is undefined if the - * specified collection is modified while the operation is in progress. - * (This implies that the behavior of this call is undefined if the - * specified collection is this collection, and this collection is - * nonempty.) + * Adds all of the elements in the specified collection to this collection (optional operation). The behavior of this operation is undefined if the specified collection is modified while the operation is in progress. (This implies that the behavior of this call is undefined if the specified collection is this collection, and this collection is nonempty.) * * @param c - collection containing elements to be added to this collection - * @throws ClassCastException - if the class of an element of the specified - * collection prevents it from being added to this collection. - * @throws NullPointerException - if the specified collection contains a - * null element and this collection does not permit null elements, or if the - * specified collection is null - * @throws IllegalArgumentException - if some property of an element of the - * specified collection prevents it from being added to this collection - * @throws IllegalArgumentException - if some property of an element of the - * specified collection prevents it from being added to this collection + * @throws ClassCastException - if the class of an element of the specified collection prevents it from being added to this collection. + * @throws NullPointerException - if the specified collection contains a null element and this collection does not permit null elements, or if the specified collection is null + * @throws IllegalArgumentException - if some property of an element of the specified collection prevents it from being added to this collection + * @throws IllegalArgumentException - if some property of an element of the specified collection prevents it from being added to this collection * @return true if this collection changed as a result of the call */ @Override - public boolean addAll(Collection c) - { + public boolean addAll(Collection c) { int sizeBefore = size(); - for (E e : c) - { + for (E e : c) { add(e); - } + } int sizeAfter = size(); return sizeAfter > sizeBefore; } @Override - public boolean removeAll(Collection c) - { + public boolean removeAll(Collection c) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override - public boolean retainAll(Collection c) - { + public boolean retainAll(Collection c) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override - public void clear() - { - // head = tail = null; - + public void clear() { + // head = tail = null; + //extra, no necessary to set the link of every node - Node p = head ; - while ( p != tail ) - { - p = p.r; - p.l = null; - } + Node p = head; + while (p != tail) { + p = p.r; + p.l = null; + } head = tail = null; } @Override - public void forEach(Consumer action) - { + public void forEach(Consumer action) { //1. use a pointer that points to the head //2. while the pointer has not reached the end of the queue //consume it Node p = head; - while ( p != null) - { + while (p != null) { action.accept(p.e); p = p.r; - } - + } + } @Override - public String toString() - { + public String toString() { String s = "PriorityQueueASDV {"; Node p = head; - while (p != null) - { + while (p != null) { s += p.e.toString(); - if (p != tail) - { + if (p != tail) { s += ", "; - } + } p = p.r; - } + } s += "}"; return s; } @Override - protected Object clone() - throws CloneNotSupportedException - { - PriorityQueueASDV c = ( PriorityQueueASDV ) super.clone(); - return c; + protected Object clone() + throws CloneNotSupportedException { + PriorityQueueASDV c = (PriorityQueueASDV) super.clone(); + return c; } - public static void main(String[] args) - { + public static void main(String[] args) { System.out.println("\n--> PriorityQueueASDV testing add"); PriorityQueueASDV pq1 = new PriorityQueueASDV(); pq1.add("Paris"); @@ -629,44 +647,32 @@ public class PriorityQueueASDV> System.out.println(pq2); System.out.println("\n\t offer null"); - try - { + try { pq1.offer(null); - } - catch (Exception e) - { + } catch (Exception e) { System.err.println(e); - } + } - try - { + try { pq2.offer(null); - } - catch (Exception e) - { + } catch (Exception e) { System.err.println(e); - } + } System.out.println(pq1); System.out.println(pq2); System.out.println("\n\t offer ClassCastException with Object"); - try - { + try { pq1.offer((String) new Object()); - } - catch (Exception e) - { + } catch (Exception e) { System.err.println(e); - } + } - try - { + try { pq2.offer((String) new Object()); - } - catch (Exception e) - { + } catch (Exception e) { System.err.println(e); - } + } System.out.println(pq1); System.out.println(pq2); @@ -680,55 +686,43 @@ public class PriorityQueueASDV> Iterator it1 = pq1.iterator(); Iterator it2 = pq2.iterator(); - while (it1.hasNext()) - { + while (it1.hasNext()) { System.out.print(it1.next() + " "); - } + } System.out.println(""); - while (it2.hasNext()) - { + while (it2.hasNext()) { System.out.print(it2.next() + " "); - } + } System.out.println(""); System.out.println("\n\t Iterator NoSuchElementException "); - try - { + try { System.out.println(it1.next()); - } - catch (NoSuchElementException e) - { + } catch (NoSuchElementException e) { System.err.println(e); - } - try - { + } + try { System.out.println(it2.next()); - } - catch (NoSuchElementException e) - { + } catch (NoSuchElementException e) { System.err.println(e); - } + } System.out.println("\n\t Iterator foreach "); it1 = pq1.iterator(); it2 = pq2.iterator(); - it1.forEachRemaining(new Consumer() - { + it1.forEachRemaining(new Consumer() { @Override - public void accept(Object t) - { + public void accept(Object t) { System.out.print(t + "*** "); } }); System.out.println(""); - it2.forEachRemaining(new Consumer() - { + it2.forEachRemaining(new Consumer() { @Override - public void accept(Object t) - { + public void accept(Object t) { System.out.print(t + "+++ "); } }); @@ -740,14 +734,14 @@ public class PriorityQueueASDV> pq2.addAll(ar1); System.out.println(pq1); System.out.println(pq2); - - System.out.println("\n\t clear" ); + + System.out.println("\n\t clear"); pq1.clear(); pq2.clear(); System.out.println(pq1); System.out.println(pq2); System.out.println(""); - + System.out.println("\n--> PriorityQueueASDV recreate priority queues from empty"); pq1.add("Paris"); pq1.add("Athens"); @@ -763,37 +757,72 @@ public class PriorityQueueASDV> pq2.add("Berlin"); pq2.add("Zurich"); System.out.println(pq1); - System.out.println(pq2); - + System.out.println(pq2); + System.out.println("\n\t forEach"); - pq1.forEach(new Consumer(){ + pq1.forEach(new Consumer() { @Override - public void accept(Object t) - { - System.out.print( t + "*** "); + public void accept(Object t) { + System.out.print(t + "*** "); } }); System.out.println(""); - pq2.forEach(new Consumer(){ + pq2.forEach(new Consumer() { @Override - public void accept(Object t) - { - System.out.print( t + "+++ "); + public void accept(Object t) { + System.out.print(t + "+++ "); } }); System.out.println(""); System.out.println("\n\t clone"); - try{PriorityQueueASDV pq1Cloned = - ( PriorityQueueASDV) pq1.clone(); - System.out.println(pq1Cloned); - pq1Cloned.add("Las Vegas"); - System.out.println(pq1Cloned); - System.out.println(pq1); + try { + PriorityQueueASDV pq1Cloned + = (PriorityQueueASDV) pq1.clone(); + System.out.println(pq1Cloned); + pq1Cloned.add("Las Vegas"); + System.out.println(pq1Cloned); + System.out.println(pq1); - } - catch(CloneNotSupportedException e ){System.err.println(e);} - - + } catch (CloneNotSupportedException e) { + System.err.println(e); + } + pq1.clear(); + pq2.clear(); + pq1.add("Paris"); + pq1.add("Athens"); + pq1.add("London"); + pq1.add("Lafayette"); + pq1.add("Berlin"); + pq1.add("Zurich"); + + pq2.add("Paris"); + pq2.add("Athens"); + pq2.add("London"); + pq2.add("Lafayette"); + pq2.add("Berlin"); + pq2.add("Zurich"); + System.out.println("----------------"); + System.out.println(pq1); + System.out.println(pq2); + + System.out.println("Attempt to remove an element."); + pq1.remove(); + pq2.remove(); + System.out.println(pq1); + System.out.println(pq2); + System.out.println("Get array of the priority queues."); + Object pqArray1[] = pq1.toArray(); + Object pqArray2[] = pq2.toArray(); + + printArrays(pqArray1); + printArrays(pqArray2); + } + + static void printArrays(Object[] arr) { + for (Object element : arr) { + System.out.print(element + ", "); + } + System.out.println(); } } diff --git a/Semester 3/ZIPs/MP5-Binary-Files_CalebFontenot.zip b/Semester 3/ZIPs/MP5-Binary-Files_CalebFontenot.zip index 4d43c5462a4b1cfbd5bc2284da1c89c0d60108a3..b14f9787dea83b5df48d8d7bd8639d314270b80e 100644 GIT binary patch delta 38942 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 RLAW57sUVQWO^|X1@*kdRCJ6ul delta 20322 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