Skip to content

Commit

Permalink
Added the ability to export the stack to a file
Browse files Browse the repository at this point in the history
  • Loading branch information
frossm committed May 12, 2023
1 parent 1bd9981 commit 771709e
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 4 deletions.
1 change: 1 addition & 0 deletions mdbook/src/Chapters/OperationalCommands.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Operational commands are commands that do not directly impact your stack numbers
|-------|-------------|
|debug|Toggle debug mode which will display additional information on what's happening internally in the program. Same as the `-D` command line switch. Probably not the useful for a normal user|
|h <br> ?|`h` or `?` will display the in-program help page|
|export `FILE`|`Export` will simply export the current stack values into the file specified. The format is very simple with one number per line. The output will be ordered as on the screen with the top of the stack item at the end of the file and the last stack item at the top. If the file exists, it will be overwritten.|
|import `FILE`|With `import` RPNCalc will replace the current stack with one loaded from a file. The file format is simple, just one number per line. Do not include any comments or alphanumeric/special characters. Just one number per line with the last number being `line1` - just like the display in RPNCalc|
|list stacks|List the current saved stacks on the system, including the one currently in use|
|list mem|Display the contents of the memory slots|
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.fross</groupId>
<artifactId>rpncalc</artifactId>
<version>4.8.1</version>
<version>4.8.2</version>
<packaging>jar</packaging>

<name>rpncalc</name>
Expand Down
2 changes: 1 addition & 1 deletion snap/snapcraft.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: rpncalc
version: '4.8.1'
version: '4.8.2'
summary: The command line Reverse Polish Notation (RPN) calculator
description: |
RPNCalc is an easy to use command line based Reverse Polish
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/fross/rpncalc/CommandParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,11 @@ public static void Parse(StackObj calcStack, StackObj calcStack2, String cmdInpu
StackOperations.cmdLoad(calcStack, calcStack2, cmdInputParam);
break;

// Export the current stack to a provided file
case "export":
StackOperations.exportStackToDisk(calcStack, cmdInputParam);
break;

// Import stack from disk
case "import":
StackOperations.importStackFromDisk(calcStack, cmdInputParam);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/fross/rpncalc/Help.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ public static void Display() {
Output.printColorln(Ansi.Color.YELLOW, "\nOperational Commands:");
Output.printColorln(Ansi.Color.WHITE, " debug Toggle DEBUG mode on/off");
Output.printColorln(Ansi.Color.WHITE, " h|? Show this help information. Either key will work");
Output.printColorln(Ansi.Color.WHITE, " export FILE Export the current stack to the provided file (one number per line)");
Output.printColorln(Ansi.Color.WHITE, " import FILE Replace current stack with file contents (one number per line)");
Output.printColorln(Ansi.Color.WHITE, " list func Display the detailed user defined functions");
Output.printColorln(Ansi.Color.WHITE, " list mem Display contents of the memory slots");
Expand Down
58 changes: 58 additions & 0 deletions src/main/java/org/fross/rpncalc/StackOperations.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
package org.fross.rpncalc;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
Expand Down Expand Up @@ -185,6 +186,63 @@ public static void cmdSwapStack(StackObj calcStack, StackObj calcStack2) {
StackManagement.ToggleCurrentStackNum();
}

/**
* ExportStackToDisk(): Save the current stack contacts to the provided file
*
* @param arg
*/
public static void exportStackToDisk(StackObj calcStack, String arg) {
String fileName = arg.trim();

// Return if no filename is given
if (arg.isEmpty()) {
Output.printColorln(Ansi.Color.RED, "Export requires a filename to be provided");
return;
}

// Ensure we have at least one item on the stack
if (calcStack.size() < 1) {
Output.printColorln(Ansi.Color.RED, "Export requires at least one item on the stack");
return;
}

Output.debugPrint("Export filename: '" + fileName + "'");

// If the file exists, then delete it
try {
File file = new File(fileName);
if (file.exists()) {
Output.debugPrint("'" + fileName + "' exists - deleting");
file.delete();
}
} catch (Exception ex) {
Output.printColorln(Ansi.Color.RED, "'" + fileName + "' exists and was not able to be deleted");
return;
}

//
try {
// Create the output filename and write the stack values to it
if (new File(fileName).createNewFile() == true) {
FileWriter fw = new FileWriter(new File(fileName));

for (int i = 0; i < calcStack.size(); i++) {
fw.write(String.valueOf(calcStack.get(i) + "\n"));
}

Output.printColorln(Ansi.Color.CYAN, "Export successful to '" + fileName + "'");

// Close the FileWriter and flush the data to the file
fw.close();
}

} catch (IOException ex) {
Output.printColorln(Ansi.Color.RED, "Could not export stack values to '" + fileName + "'");
return;
}

}

/**
* LoadStackFromDisk(): Load the contents of a file into the stack. The file should have one stack item per line
*
Expand Down
72 changes: 70 additions & 2 deletions src/test/java/org/fross/rpncalc/StackOperationsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;

Expand Down Expand Up @@ -163,6 +167,70 @@ void testLoadCommand() {
}
}

/**
* Test stack output to file
*/
@Test
void textExport() {
String testFileName = "target/rpncalc.export";
File testFile = new File(testFileName);
Double[] testValues = { -1.0123, 2.0234, 3.0345, -15.0456, 2.0567, 17.0678, 38.0789, 53.0891, 14.0123, 73.0234, 72.0345, 72.0456, 10.0567, 83.0678,
-60.0789, 76.0890, 59.090, 30.0234, -42.0345, 89.0456, 30.0567, 44.0678, -31.0789 };

// Build the StackObject
StackObj stk = new StackObj();
for (int i = 0; i < testValues.length; i++) {
stk.push(testValues[i]);
}
assertEquals(23, stk.size());

// Delete the testFile if it exists
try {
testFile.delete();
} catch (Exception ex) {
Output.println("Testing Export: Issue deleting test file: ' " + testFileName + "'");
}

// Export the file and see if it looks OK
StackOperations.exportStackToDisk(stk, testFileName);
assertTrue(testFile.exists());
assertTrue(testFile.isFile());
assertTrue(testFile.length() > 0);

// Import the stack from the file and compare
try {
// Verify the filename provided is a file and can be read
if (new File(testFileName).canRead() && new File(testFileName).isFile()) {
// Read lines from the file into the ArrayList
ArrayList<String> linesRead = new ArrayList<>(Files.readAllLines(Paths.get(testFileName)));

// Test that read-from-file value = test value
for (int i = 0; i < testValues.length; i++) {
assertEquals(testValues[i].toString(), linesRead.get(i));
}
} else {
throw new IOException();
}
} catch (IOException ex) {
Output.printColorln(Ansi.Color.RED, "ERROR: Could not read from the file '" + testFileName + "'");
Output.printColorln(Ansi.Color.RED, "ERROR: Please note the file must be in lower case");

} catch (NumberFormatException ex) {
Output.printColorln(Ansi.Color.RED, "The data in '" + testFileName
+ "' can't be read as it is not in the correct format.\nThe import file format is simply one number per line");
}

// Delete the test import file
try {
File file = new File(testFileName);
file.delete();
assertFalse(testFile.exists());
} catch (Exception ex) {
Output.println("Testing Export: Issue deleting test file: ' " + testFileName + "'");
}

}

/**
* Test import capabilities
*/
Expand All @@ -175,11 +243,12 @@ void testImport() {
try {
FileWriter fw = new FileWriter(new File(testFileName.toLowerCase()));

// Loop through the test values and compare
for (int i = 0; i < testValues.length; i++) {
fw.write(testValues[i] + "\n");
}

// Remove testfile
// Close the FileWriter
fw.close();

} catch (Exception ex) {
Expand All @@ -192,7 +261,6 @@ void testImport() {

// Verify the import values match the file data
for (int i = 0; i < testValues.length; i++) {
Output.println("Testing Import: TestValues:" + testValues[i] + "\t| StackValues: " + stk.get(i));
assertEquals(testValues[i], stk.get(i));
}

Expand Down

0 comments on commit 771709e

Please sign in to comment.