diff --git a/src/main/java/com/amigoscode/_2_developers/_10_exceptions/CustomException.java b/src/main/java/com/amigoscode/_2_developers/_10_exceptions/CustomException.java index d9387f2..cae9dbb 100644 --- a/src/main/java/com/amigoscode/_2_developers/_10_exceptions/CustomException.java +++ b/src/main/java/com/amigoscode/_2_developers/_10_exceptions/CustomException.java @@ -2,7 +2,7 @@ /** * Custom Exception Exercises - * + *

* Practice creating custom checked and unchecked exceptions, throwing them * from methods, catching them, and using exception chaining. */ @@ -25,6 +25,15 @@ public class CustomException { // - Have a constructor that takes a String message and a Throwable cause, // and calls super(message, cause) // Define it as a static inner class here. + public static class InvalidAgeException extends RuntimeException { + public InvalidAgeException(String message) { + super(message); + } + + public InvalidAgeException(String message, Throwable cause) { + super(message, cause); + } + } // TODO: 3 - Create a static inner class BankAccount with: @@ -35,11 +44,38 @@ public class CustomException { // message and the shortfall amount (amount - balance). // Otherwise, subtract amount from balance. // - A method: double getBalance() + public static class BankAccount { + private double balance; + + public BankAccount(double initialBalance) { + this.balance = initialBalance; + } + + public void withdraw(double amount) throws InsufficientFundsException { + if (amount > this.balance) { + throw new InsufficientFundsException("The amount you entered is larger than your current balance", + (amount - this.balance)); + } + + this.balance = amount - this.balance; + } + + public double getBalance() { + return this.balance; + } + } // TODO: 4 - Create a static method: void validateAge(int age) // If age < 0 or age > 150, throw a new InvalidAgeException with an appropriate message. // Otherwise, print "Age " + age + " is valid." + public static void validateAge(int age) { + if (age < 0 || age > 150) { + throw new InvalidAgeException("Age is greater than or less than the provided age range of 0 to 150"); + } + + System.out.println("Age " + age + " is valid."); + } public static void main(String[] args) { @@ -50,7 +86,18 @@ public static void main(String[] args) { // Catch the exception and print its message and the shortage amount. // Also try validateAge with valid (25) and invalid (-5) values, // catching InvalidAgeException. + BankAccount myAccount = new BankAccount(100); + try { + myAccount.withdraw(50); + System.out.println(myAccount.getBalance()); + myAccount.withdraw(75); + System.out.println(myAccount.getBalance()); + validateAge(25); + validateAge(-5); + } catch (InsufficientFundsException | InvalidAgeException e) { + System.out.println("Exception: " + e.getClass().getSimpleName() + "-" + e.getMessage()); + } System.out.println("\n=== Exception Chaining ==="); // TODO: 6 - Demonstrate exception chaining: @@ -61,6 +108,15 @@ public static void main(String[] args) { // In an outer try-catch, catch the InvalidAgeException and print: // - The exception message // - The cause (using getCause()) - + try { + try { + System.out.println(Integer.parseInt("abc")); + } catch (NumberFormatException e) { + throw new InvalidAgeException("Age must be a valid number", e); + } + } catch(InvalidAgeException e) { + System.out.println("Exception message: " + e.getMessage()); + System.out.println("Cause: " + e.getCause()); + } } } diff --git a/src/main/java/com/amigoscode/_2_developers/_10_exceptions/InsufficientFundsException.java b/src/main/java/com/amigoscode/_2_developers/_10_exceptions/InsufficientFundsException.java new file mode 100644 index 0000000..816684d --- /dev/null +++ b/src/main/java/com/amigoscode/_2_developers/_10_exceptions/InsufficientFundsException.java @@ -0,0 +1,14 @@ +package com.amigoscode._2_developers._10_exceptions; + +public class InsufficientFundsException extends Exception { + private final double amount; + + public InsufficientFundsException(String message, double amount) { + super(message); + this.amount = amount; + } + + public double getAmount() { + return this.amount; + } +} diff --git a/src/main/java/com/amigoscode/_2_developers/_10_exceptions/TryCatch.java b/src/main/java/com/amigoscode/_2_developers/_10_exceptions/TryCatch.java index afefa02..c4e97b0 100644 --- a/src/main/java/com/amigoscode/_2_developers/_10_exceptions/TryCatch.java +++ b/src/main/java/com/amigoscode/_2_developers/_10_exceptions/TryCatch.java @@ -4,7 +4,7 @@ /** * Try-Catch Exercises - * + *

* Practice exception handling: try-catch, finally, multi-catch, try-with-resources, * throwing exceptions, and exception propagation. */ @@ -23,7 +23,12 @@ public static int safeArrayAccess(int[] arr, int index) { // try to return arr[index]. // catch ArrayIndexOutOfBoundsException, print "Index out of bounds: " + index, // and return -1. - return 0; + try { + return arr[index]; + } catch (ArrayIndexOutOfBoundsException e) { + System.out.println("Index out of bounds: " + index); + return -1; + } } /** @@ -36,7 +41,12 @@ public static int safeArrayAccess(int[] arr, int index) { public static int safeParseInt(String text) { // TODO: 2 - Wrap Integer.parseInt(text) in a try-catch block. // catch NumberFormatException, print "Cannot parse: " + text, and return 0. - return 0; + try { + return Integer.parseInt(text); + } catch (NumberFormatException e) { + System.out.println("Cannot parse: " + text); + return 0; + } } /** @@ -54,6 +64,13 @@ public static int divideWithFinally(int a, int b) { // finally: print "Division operation completed." // Return the result. (You'll need a local variable since return in try // executes after finally.) + try { + return a/b; + } catch(ArithmeticException e) { + System.out.println("Cannot divide by zero!"); + } finally { + System.out.println("Division operation completed."); + } return 0; } @@ -72,6 +89,12 @@ public static int multiCatchDemo(String[] data, int index) { // Catch both ArrayIndexOutOfBoundsException and NumberFormatException // in a single catch block using: catch (ExType1 | ExType2 e) // Print "Error: " + e.getMessage() and return -1. + try { + String element = data[index]; + return Integer.parseInt(element); + } catch(ArrayIndexOutOfBoundsException | NumberFormatException e) { + System.out.println(e.getMessage()); + } return 0; } @@ -89,7 +112,12 @@ public static int tryWithResourcesDemo(String input) { // } // catch any exception and return -1. // The Scanner will be automatically closed after the try block. - return 0; + try (Scanner scanner = new Scanner(input)) { + return scanner.nextInt(); + } catch(Exception e) { + System.out.println(e.getMessage()); + return -1; + } } /** @@ -99,10 +127,13 @@ public static int tryWithResourcesDemo(String input) { * @return the validated age * @throws IllegalArgumentException if age is negative */ - public static int validateAge(int age) { + public static int validateAge(int age) throws IllegalArgumentException{ // TODO: 6 - If age < 0, throw a new IllegalArgumentException // with the message "Age cannot be negative: " + age. // Otherwise, return age. + if (age < 0) { + throw new IllegalArgumentException("Age cannot be negative: " + age); + } return age; } @@ -112,7 +143,7 @@ public static int validateAge(int age) { * * @param value a string that should contain a positive number * @return the validated positive number - * @throws NumberFormatException if value is not a number + * @throws NumberFormatException if value is not a number * @throws IllegalArgumentException if the number is negative */ public static int processValue(String value) { @@ -120,7 +151,7 @@ public static int processValue(String value) { // Then call validateAge() with the parsed int. // Do NOT catch any exceptions here — let them propagate to the caller. // This demonstrates that exceptions travel up the call stack. - return 0; + return validateAge(Integer.parseInt(value)); } public static void main(String[] args) { @@ -133,7 +164,6 @@ public static void main(String[] args) { System.out.println("\n=== Safe Parse Int ==="); System.out.println("Parse '42': " + safeParseInt("42")); System.out.println("Parse 'abc': " + safeParseInt("abc")); - System.out.println("\n=== Finally Block ==="); System.out.println("10 / 2 = " + divideWithFinally(10, 2)); System.out.println("10 / 0 = " + divideWithFinally(10, 0)); @@ -148,6 +178,7 @@ public static void main(String[] args) { System.out.println("Parse '123': " + tryWithResourcesDemo("123")); System.out.println("Parse 'xyz': " + tryWithResourcesDemo("xyz")); + System.out.println("\n=== Throw Exception ==="); try { validateAge(25); @@ -164,5 +195,6 @@ public static void main(String[] args) { } catch (Exception e) { System.out.println("Propagated exception: " + e.getClass().getSimpleName() + " - " + e.getMessage()); } + } } diff --git a/src/main/java/com/amigoscode/_2_developers/_11_files/FileReading.java b/src/main/java/com/amigoscode/_2_developers/_11_files/FileReading.java index 060e990..2f93186 100644 --- a/src/main/java/com/amigoscode/_2_developers/_11_files/FileReading.java +++ b/src/main/java/com/amigoscode/_2_developers/_11_files/FileReading.java @@ -6,15 +6,17 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Stream; /** * File Reading Exercises - * + *

* Practice reading files using both the modern java.nio.file API and the * classic java.io API. Always use try-with-resources for readers and streams * to ensure they are properly closed. - * + *

* NOTE: Before running these exercises, create a test file at "test-input.txt" * in the project root with several lines of text. */ @@ -30,7 +32,7 @@ public class FileReading { public static List readAllLines(String filePath) throws IOException { // TODO: 1 - Use Files.readAllLines(Path.of(filePath)) to read all lines. // Return the resulting List. - return null; + return Files.readAllLines(Path.of(filePath)); } /** @@ -46,6 +48,14 @@ public static void readWithBufferedReader(String filePath) throws IOException { // read lines in a loop using reader.readLine() until it returns null. // Print each line. // } + try ( + BufferedReader reader = new BufferedReader(new FileReader(filePath)); + ) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + } } @@ -60,7 +70,14 @@ public static long countLines(String filePath) throws IOException { // TODO: 3 - Read the file line by line and count the lines. // You can use Files.readAllLines() and call .size(), // or use Files.lines() with .count() for a stream-based approach. - return 0; + + // First Approach + // return Files.readAllLines(Path.of(filePath)).size(); + + // Second Approach - Better for bigger files + try (Stream lines = Files.lines(Path.of(filePath))) { + return lines.count(); + } } /** @@ -76,7 +93,20 @@ public static List searchWord(String filePath, String word) throws IOExc // Filter the lines to only include those that contain the given word. // Hint: use a for loop and an ArrayList to collect matching lines, // or use Files.readAllLines().stream().filter(...).toList() - return null; + + // 1st Approach +// List files = Files.readAllLines(Path.of(filePath)); +// List matchingWords = new ArrayList<>(); +// for (String file : files) { +// if (file.contains(word)) { +// matchingWords.add(file); +// } +// } +// return matchingWords; + + // 2nd Approach + return Files.readAllLines(Path.of(filePath)).stream().filter(file -> file.contains(word)).toList(); + } /** @@ -89,7 +119,7 @@ public static List searchWord(String filePath, String word) throws IOExc public static String readFileAsString(String filePath) throws IOException { // TODO: 5 - Use Files.readString(Path.of(filePath)) to read the entire file // as a single String. Return it. - return null; + return Files.readString(Path.of(filePath)); } /** @@ -103,6 +133,13 @@ public static String handleMissingFile(String filePath) { // Catch FileNotFoundException (or NoSuchFileException) and return // "File not found: " + filePath. // Catch IOException and return "Error reading file: " + e.getMessage(). + try { + return Files.readString(Path.of(filePath)); + } catch (FileNotFoundException e) { + System.out.println("File not found: " + filePath); + } catch (IOException e) { + System.out.println("Error reading file: " + e.getMessage()); + } return null; } @@ -116,13 +153,13 @@ public static void main(String[] args) throws IOException { System.out.println("=== Read All Lines ==="); List lines = readAllLines(testFile); if (lines != null) lines.forEach(System.out::println); - System.out.println("\n=== BufferedReader ==="); readWithBufferedReader(testFile); System.out.println("\n=== Count Lines ==="); System.out.println("Number of lines: " + countLines(testFile)); + System.out.println("\n=== Search Word ==="); List results = searchWord(testFile, "Java"); if (results != null) results.forEach(l -> System.out.println("Found: " + l)); diff --git a/src/main/java/com/amigoscode/_2_developers/_11_files/FileWriting.java b/src/main/java/com/amigoscode/_2_developers/_11_files/FileWriting.java index f5cd385..35d5766 100644 --- a/src/main/java/com/amigoscode/_2_developers/_11_files/FileWriting.java +++ b/src/main/java/com/amigoscode/_2_developers/_11_files/FileWriting.java @@ -3,14 +3,14 @@ import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; +import java.io.PrintWriter; +import java.nio.file.*; +import java.util.Arrays; import java.util.List; /** * File Writing Exercises - * + *

* Practice writing to files using the modern java.nio.file API and the * classic java.io API. Learn to write, append, and copy files. */ @@ -27,6 +27,13 @@ public class FileWriting { public static void writeString(String filePath, String content) throws IOException { // TODO: 1 - Use Files.writeString(Path.of(filePath), content) to write the content. // This creates the file if it doesn't exist, or overwrites it if it does. + Files.writeString(Path.of(filePath), content); +// try ( +// FileWriter fileWriter = new FileWriter(filePath, true); +// PrintWriter writer = new PrintWriter(fileWriter); +// ) { +// writer.print(content); +// } } @@ -41,7 +48,7 @@ public static void appendToFile(String filePath, String text) throws IOException // TODO: 2 - Use Files.writeString with StandardOpenOption.APPEND to append text. // Add a newline ("\n") before the text so it appears on a new line. // Example: Files.writeString(Path.of(filePath), "\n" + text, StandardOpenOption.APPEND); - + Files.writeString(Path.of(filePath), "\n" + text, StandardOpenOption.APPEND); } /** @@ -54,7 +61,7 @@ public static void appendToFile(String filePath, String text) throws IOException public static void writeLines(String filePath, List lines) throws IOException { // TODO: 3 - Use Files.write(Path.of(filePath), lines) to write all lines. // Each string in the list becomes one line in the file. - + Files.write(Path.of(filePath), lines); } /** @@ -73,6 +80,15 @@ public static void writeWithBufferedWriter(String filePath) throws IOException { // writer.newLine(); // writer.write("Line 3"); // } + try ( + BufferedWriter writer = new BufferedWriter(new FileWriter(filePath)) + ) { + writer.write("Line 1"); + writer.newLine(); + writer.write("Line 2"); + writer.newLine(); + writer.write("Line 3"); + } } @@ -89,6 +105,7 @@ public static void copyFile(String sourcePath, String destinationPath) throws IO // or Files.copy(Path.of(sourcePath), Path.of(destinationPath)) for a direct copy. // Note: Files.copy will throw if destination already exists unless you add // StandardCopyOption.REPLACE_EXISTING. + Files.copy(Path.of(sourcePath), Path.of(destinationPath), StandardCopyOption.REPLACE_EXISTING); } @@ -107,6 +124,17 @@ public static void writeCsv(String filePath, String[] headers, String[][] rows) // Use StringBuilder or String.join(",", array) to build each line. // Write the complete result using Files.writeString(). + StringBuilder sb = new StringBuilder(); + + sb.append(String.join(",", headers)).append("\n"); + + for (String[] row : rows) { + sb.append(String.join(",", row)).append("\n"); + } + + Files.writeString(Path.of(filePath), sb.toString()); + + } public static void main(String[] args) throws IOException { @@ -125,7 +153,6 @@ public static void main(String[] args) throws IOException { writeLines(baseDir + "/lines-test.txt", List.of("Apple", "Banana", "Cherry")); System.out.println("Lines written:"); Files.readAllLines(Path.of(baseDir + "/lines-test.txt")).forEach(System.out::println); - System.out.println("\n=== BufferedWriter ==="); writeWithBufferedWriter(baseDir + "/buffered-test.txt"); System.out.println("BufferedWriter output:"); @@ -149,6 +176,11 @@ public static void main(String[] args) throws IOException { // Clean up Files.walk(Path.of(baseDir)) .sorted(java.util.Comparator.reverseOrder()) - .forEach(p -> { try { Files.delete(p); } catch (IOException ignored) {} }); + .forEach(p -> { + try { + Files.delete(p); + } catch (IOException ignored) { + } + }); } }