Exceptions and Files in Java

Learn how Java reports problems while a program runs and how to deal with them. Read stack traces, tell checked from unchecked exceptions, and handle errors with try, catch and finally. Throw your own exceptions and design exception classes that say exactly what went wrong. Then read and write text files with paths, encodings and line endings under control, close every file safely with try-with-resources, and build a program that copes with missing files and bad data.

BeginnerLesson 9 of 11 in Object-Oriented Programming with Java Course

What you will learn

  1. Recognize an exception when a program fails, read the stack trace to find where and why it happened, and place any exception in Java's class hierarchy as checked or unchecked.
    • Read an exception and its stack trace
      Explain what happens when a statement throws an exception, name the common runtime exceptions and their causes, and use a stack trace to locate the problem.
    • Classify exceptions as checked or unchecked
      Place any exception in the hierarchy below Throwable, decide whether it is checked or unchecked, and apply the rule that checked exceptions must be caught or declared.
  2. Catch the exceptions a program can expect, recover from them in a sensible way, handle several kinds in the right order, and run cleanup code whatever happens.
    • Catch an exception and recover
      Write a try-catch statement, trace how control moves through it, and recover from bad input instead of letting the program crash.
    • Handle several exception types in the right order
      Use several catch clauses or a multi-catch, order them from specific to general, and decide where a try block should start and end.
    • Run cleanup code with finally
      Add a finally block, trace when it runs in every path through a try statement, and avoid the mistakes that make finally hide problems.
  3. Signal problems from your own methods with throw, declare checked exceptions with throws, and create exception classes that tell callers exactly what went wrong.
    • Throw exceptions and declare them with throws
      Validate arguments and object state by throwing standard exceptions, declare checked exceptions in method headers, and decide where an exception should be handled.
    • Create custom exception classes and keep the cause
      Write your own checked or unchecked exception classes, throw them before changing an object's state, and wrap a low-level exception without losing it.
  4. Point a program at the right file, understand how text is stored as bytes and lines, and make sure every opened file is closed with try-with-resources.
    • Work with paths, encodings and line endings
      Build paths to files, predict where Java looks for a relative path, and explain how character encodings, line endings and number formats affect text files.
    • Close resources automatically with try-with-resources
      Use try-with-resources to open and close files and other resources, predict the closing order, and explain how it keeps exceptions from being lost.
  5. Read text files line by line and turn their lines into data, write and append results to files, and combine everything into a program that copes with missing files and bad records.
    • Read a text file and turn its lines into data
      Read a file with Scanner, Files.readAllLines or BufferedReader, split and convert each line, and skip or report lines that do not fit the expected format.
    • Write and append text files
      Write text to a new or existing file, append without erasing what is there, and make sure everything written actually reaches the file.
    • Build a robust file-processing program
      Combine reading, parsing, exceptions and writing in one program that stops cleanly on whole-file failures, skips and reports bad records, and avoids partial output.

Exceptions and Files in Java study guide

5 chapters

1

Understand what exceptions are and how Java classifies them

A program can compile successfully and still fail when it receives an empty array, invalid text, or a missing file. The exception object and its stack trace give you evidence about that failure. Read the trace back through the active method calls, then use the class hierarchy to decide whether Java requires a handling decision at compile time. This prepares you to distinguish bugs to fix from expected problems your program can recover from.

1.1 Find the failing statement

An exception is an object describing a problem that interrupts a running program. Throwing it stops the current statement. Java skips the remaining normal work until it finds a matching handler; without one, the exception passes back through the methods that called it.

Recognize the kind of problem

A missing semicolon is a compile-time error: the program cannot compile. An exception occurs when compiled code runs with data that triggers a problem.

ExceptionTypical trigger
ArithmeticExceptionInteger division by zero
ArrayIndexOutOfBoundsExceptiona[3] when the array has length 3
IndexOutOfBoundsExceptionlist.get(list.size())
NullPointerExceptionCalling a method through null
NumberFormatExceptionInteger.parseInt("12a")
InputMismatchExceptionScanner.nextInt() meets "ten"
ClassCastExceptionCasting an object to a class it does not belong to

Array indexes start at 0, so length 3 means valid indexes 0, 1 and 2. Floating-point division follows different rules: 10.0 / 0 produces Infinity; it does not throw the integer-division exception.

Read a trace from the top

Here is a complete class, with no blank lines before the first line:

public class Average {
    static int average(int[] values) {
        int sum = 0;
        for (int value : values) sum += value;
        return sum / values.length;
    }
    public static void main(String[] args) {
        int[] values = new int[0];
        System.out.println(average(values));
    }
}

The array is empty, so its length is 0. The division on line 5 fails. The trace is:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Average.average(Average.java:5)
    at Average.main(Average.java:9)
  1. Read the first line for the exception class and message.
  2. Read the top at frame for the point where the problem was detected.
  3. Read downward for callers: main called average on line 9.
  4. If the top frames belong to Java's library, find the first frame naming your own class. For a failed Integer.parseInt, library frames can precede the call in your code.

The trace follows the call stack, the chain of active method calls. It tells you where to investigate, but the bad value may have been created earlier. Here the division detects the problem; the caller supplied the empty array. Decide whether an empty input should be rejected or handled before computing an average.

Inspect the exception object

e.getMessage() returns the message and can return null. e.toString() includes the class name and, when present, the message. e.printStackTrace() prints the trace to standard error. A Caused by: section shows an earlier exception retained inside a wrapper.

JVM-generated NullPointerException messages normally identify the null expression. An explicitly created exception can instead have a custom message or none. Follow the reference back to where it should have received an object.

An unhandled exception leaving main ends the main thread; that ends a single-threaded program. Fix bugs such as wrong indexes in the code. Plan recovery for expected external problems, such as a missing file or invalid user input.

Key Takeaways

  • An exception interrupts normal execution; skipped statements do not resume automatically.
  • Read the exception class and message, then follow stack frames from the detected failure to its callers.
  • Library frames can appear before the first frame in your own code.
  • The failing statement may reveal a bad value created earlier.
  • Fix programming bugs and handle expected input or file failures.

1.2 Checked and unchecked exceptions

Exception classes use the inheritance rules you already know. A thrown subclass object also belongs to its superclass, which explains both Java's exception categories and how a handler matches them.

Follow the hierarchy

Only objects of Throwable or its subclasses can be thrown. Two main branches sit below it:

Throwable
  Error
    OutOfMemoryError
    StackOverflowError
  Exception
    RuntimeException
      IllegalArgumentException
        NumberFormatException
      NullPointerException
      IndexOutOfBoundsException
        ArrayIndexOutOfBoundsException
    IOException
      FileNotFoundException
      NoSuchFileException

Error describes serious failures of the running environment. An ordinary application should not try to recover from an exhausted heap or a stack exhausted by endless recursion. Exception describes problems an application may handle, including its RuntimeException branch.

CategoryClassesCompiler requirement
UncheckedRuntimeException, Error, and their subclassesCatching or declaring is optional
CheckedAll other Throwable subclassesCatch or declare when the code can throw them

Both kinds are thrown at run time. The word "checked" describes the compiler checking your handling, not an earlier moment when the failure occurs. Unchecked also does not mean harmless: an unhandled null reference can stop a program.

Apply catch or declare

Reading a file can fail even in correct code. A helper can leave the decision to its caller:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

class Names {
    static List<String> load(Path file) throws IOException {
        return Files.readAllLines(file);
    }
}

Files.readAllLines can throw the checked IOException. The declaration passes that possibility to the caller, which must catch it or declare it too. Removing throws IOException without adding a handler makes the helper fail compilation. A method using Integer.parseInt has no comparable compiler obligation because NumberFormatException is unchecked.

Checked failures often describe conditions a caller can plan for, such as a file disappearing. Runtime failures often identify bugs or invalid arguments. These are useful design reasons, but the superclass chain determines the category. A custom class extending RuntimeException remains unchecked even when a caller could recover.

Match handlers through inheritance

catch (IOException e) can handle a FileNotFoundException or NoSuchFileException. catch (Exception e) also catches runtime exceptions; it can turn a coding bug into a misleading input message. catch (Throwable e) reaches the Error branch too and is rarely appropriate for ordinary recovery.

To classify an unfamiliar class, trace its inheritance upward in the API documentation. InputMismatchException extends NoSuchElementException, which extends RuntimeException, so it is unchecked. InterruptedException extends Exception outside the runtime branch, so it is checked. Declaring an unchecked type in a throws clause is allowed, but does not change its category.

Key Takeaways

  • RuntimeException, Error, and all their subclasses are unchecked.
  • Other Throwable subclasses are checked; code that can throw them must catch or declare them.
  • Both checked and unchecked exceptions occur at run time.
  • A catch for a superclass also matches its subclasses.
  • A broad Exception handler can hide programming bugs.
  • Classify an unfamiliar exception by its superclass chain.
2

Handle exceptions with try, catch and finally

Handling a failure changes which statements run next. A useful handler must match the exception and leave the program ready to continue, while cleanup must also run on paths that leave early. Follow conversions and loops step by step, choose specific handlers before general ones, and place the protected block around the work that should fail together. Then trace how finally behaves when an exception propagates or a method returns.

2.1 Recover from a failed conversion

A try block marks work that may fail. A matching catch block gives the program a useful next action, such as asking for another value. Handling the exception does not retry the failed statement by itself.

Trace the branches
System.out.println("A");
try {
    System.out.println("B");
    int value = Integer.parseInt("4x");
    System.out.println("C");
} catch (NumberFormatException e) {
    System.out.println("D: " + e.getMessage());
}
System.out.println("E");

The output is A, B, D: For input string: "4x", and E, each on its own line. The conversion fails, so Java skips C and enters the matching handler. When that handler finishes normally, execution continues after the whole statement. If conversion succeeds, the handler is skipped. If the block throws an ArithmeticException, this handler does not match; that exception propagates.

Retry with fresh input

Read an entire line before converting it. The loop below accepts a whole number and handles the end of keyboard input by reporting that no value was supplied:

import java.util.Scanner;

class WholeNumbers {
    static int readWholeNumber(Scanner in) {
        while (in.hasNextLine()) {
            String line = in.nextLine();
            try {
                return Integer.parseInt(line.trim());
            } catch (NumberFormatException e) {
                System.out.println("Please enter a whole number.");
            }
        }
        throw new IllegalStateException("No number supplied");
    }
}

For inputs "twenty" and "20", the handler prints once, the loop reads a new line, and the method returns 20. trim() removes surrounding whitespace: Integer.parseInt(" 20") otherwise fails. The conversion accepts an optional sign and digits representing an in-range integer.

A token-based scanner needs a different repair. When nextInt() meets "ten", its InputMismatchException leaves that token unread. Catching and calling nextInt() again repeats the failure forever. Consume the bad token with next() or discard the line with nextLine() before retrying. hasNextInt() can check a token before conversion.

Keep the recovered state usable

A variable declared inside try exists only in that block. If later code needs the result, declare it outside and make every continuing path assign a valid value:

int quantity;
try {
    quantity = Integer.parseInt("bad");
} catch (NumberFormatException e) {
    quantity = 0;
}
System.out.println(quantity);

Zero is appropriate here only if the program defines it as a valid fallback. Leaving quantity unassigned in the handler causes a compile-time definite-assignment error.

Catch the narrow type you can handle. An empty handler silently loses the problem; a broad catch (Exception e) can label a null-reference bug as a bad number. Recovery should ask again, skip one item, choose a valid default, report failure, or pass a meaningful exception onward. For simple predictable boundaries, check first: index >= 0 && index < list.size() prevents both negative and too-large list indexes.

Key Takeaways

  • A matching handler runs after the rest of the failing try block is skipped.
  • A loop must read new input before trying again.
  • Scanner.nextInt() leaves a mismatched token unread.
  • Every path that continues must leave later variables initialized sensibly.

2.2 Choose handlers and the work they protect

A file can be missing, unreadable, or full of malformed records. Those failures need different responses. Several handlers let one try distinguish them, while the block's position decides how much work stops when something fails.

Put specific handlers first

Java tests handlers from top to bottom and runs the first matching one. It does not keep running later handlers for the same exception.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;

class FirstCount {
    static void show(Path file) {
        try {
            int count = Integer.parseInt(Files.readString(file).trim());
            System.out.println(count);
        } catch (NoSuchFileException e) {
            System.out.println("File not found: " + file.toAbsolutePath());
        } catch (IOException e) {
            System.out.println("Could not read: " + file.toAbsolutePath());
        } catch (NumberFormatException e) {
            System.out.println("The file must contain one whole number.");
        }
    }
}

NoSuchFileException extends IOException, so it must come first. Reversing them makes the specific handler unreachable and prevents compilation. The conversion exception is unrelated to IOException, so those two handlers can appear in either order.

A checked handler must also be relevant to the protected work. Catching IOException around only int count = 5; is rejected because that block cannot throw it. This restriction does not apply in the same way to unchecked types or the broad Exception and Throwable types.

Share a handler when the response is shared

A multi-catch joins unrelated exception types with |:

try {
    String[] parts = "Ana".split(",");
    int age = Integer.parseInt(parts[1]);
    System.out.println(age);
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
    System.out.println("Invalid record: " + e.getMessage());
}

Here the missing second field triggers the index exception. A present but nonnumeric field would trigger the conversion exception, and both receive the same response. The multi-catch parameter is implicitly final. Alternatives cannot be a subclass and its superclass: FileNotFoundException | IOException is invalid because IOException already covers both.

Decide what one failure should skip

Consider the texts "3", "x", and "5". With a try around the whole loop, processing stops at "x" and the sum so far is 3. Put the try inside the loop to recover separately for each item:

int sum = 0;
for (String text : new String[] {"3", "x", "5"}) {
    try {
        sum += Integer.parseInt(text);
    } catch (NumberFormatException e) {
        System.out.println("Skipped: " + text);
    }
}
System.out.println(sum);

This prints Skipped: x and then 8. The loop continues because its body handled that record's failure. Nested handlers search outward from the innermost protected block; a nonmatching inner handler leaves an outer one a chance. Choose the smallest unit of work that should fail together: one record for bad data, the file operation for a read failure.

Key Takeaways

  • Java runs at most one matching handler for each exception.
  • Catch a subclass before its superclass.
  • Multi-catch shares a response across unrelated exception types.
  • Multi-catch cannot combine a superclass with its subclass.
  • Put record-level recovery inside the loop to continue with later records.

2.3 Run cleanup before control leaves

Some work must happen whether an operation succeeds or fails. A finally block runs as control leaves its try statement, including when an exception propagates or a method returns.

Follow an unmatched exception
try {
    System.out.println("1");
    int[] values = new int[2];
    values[2] = 7;
    System.out.println("2");
} catch (NumberFormatException e) {
    System.out.println("3");
} finally {
    System.out.println("4");
}
System.out.println("5");

Only 1 and 4 print before the ArrayIndexOutOfBoundsException propagates. Index 2 is outside the two-element array. The handler does not match, but finally still runs. The statement printing 5 is outside the cleanup block, so the propagating exception skips it.

If the protected work instead throws a matching NumberFormatException after printing 1, the handler prints 3, cleanup prints 4, and execution continues to 5. On a successful path, no handler runs, but cleanup still does.

Return values are prepared before cleanup
class Cleanup {
    static int result() {
        try {
            return 1;
        } finally {
            System.out.println("cleanup");
        }
    }
}

The return expression is evaluated first. Java then prints cleanup, and the caller receives 1. A break or continue leaving a protected region also runs its cleanup before the control transfer takes effect.

Keep return out of finally. A return 2; there would replace the pending return value and could even discard a pending exception. An exception thrown by cleanup can likewise replace the original failure. Cleanup should not introduce a second competing result. The compiler's -Xlint:finally option warns when a finally block cannot complete normally.

Close an object only if it opened

The older manual pattern needs a variable visible to the cleanup block:

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Scanner;

class ManualRead {
    static void firstLine(Path file) throws IOException {
        Scanner sc = null;
        try {
            sc = new Scanner(file, StandardCharsets.UTF_8);
            if (sc.hasNextLine()) System.out.println(sc.nextLine());
            if (sc.ioException() != null) throw sc.ioException();
        } finally {
            if (sc != null) sc.close();
        }
    }
}

If opening fails, sc is still null, so the guard prevents cleanup from throwing a new null-reference exception. For closeable objects, try-with-resources removes this bookkeeping and handles competing failures more safely.

finally is not a guarantee against the machine stopping. System.exit ends the JVM without running this cleanup; a crash or power loss also prevents it. An infinite loop that never leaves the block never reaches its finally either.

Key Takeaways

  • finally runs on normal completion, caught and uncaught exceptions, and control transfers such as return.
  • A return expression is evaluated before cleanup runs.
  • Code after a try statement is skipped when an exception propagates; finally is still reached.
  • A return or thrown exception in finally can hide the original result.
  • Try-with-resources is the usual choice for closing file resources.
  • JVM termination or a block that never ends can prevent cleanup.
3

Throw exceptions and design your own

An invalid request is easiest to diagnose before it changes an object. Your methods can reject bad arguments or state with standard exceptions, and expose domain problems with custom classes. The method declaration tells callers about checked failures; inheritance limits what an override can add. When translating a low-level failure into a more useful one, retain its cause so that the caller gets both context and the original diagnostic evidence.

3.1 Signal invalid arguments and state

Your methods can reject invalid requests before changing an object. Choose an exception that identifies the problem and lets the caller respond.

Throw an object now
class Percentage {
    private int value;

    public void setPercentage(int value) {
        if (value < 0 || value > 100) {
            throw new IllegalArgumentException(
                "percentage must be 0 to 100, was " + value);
        }
        this.value = value;
    }
}

Calling setPercentage(120) throws with the message percentage must be 0 to 100, was 120. The assignment has not run, so the field retains its previous value. This is failing fast: report the invalid request at the point where you can explain it. The same check in a constructor prevents an invalid object from being returned.

throw needs an exception object, as in throw new IllegalArgumentException("bad quantity");. A class name alone is not an object. An ordinary statement directly after an unconditional throw in the same block is unreachable.

ProblemStandard exception
Argument has an invalid valueIllegalArgumentException
Object is in the wrong state for the callIllegalStateException
Required object reference is nullNullPointerException
Operation is not offered by the classUnsupportedOperationException
Position is outside a collectionIndexOutOfBoundsException

Objects.requireNonNull(name, "name must not be null"), from java.util.Objects, is a convenient null check. An already-sent order rejecting another item is a state problem; a negative item quantity is an argument problem.

Declare what can leave the method

A file-reading helper can declare its checked failure:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

class NameLoader {
    static List<String> loadNames(Path file) throws IOException {
        return Files.readAllLines(file);
    }
}

throw is an executable statement. throws belongs to the method declaration and tells callers what checked failures they must address. It neither catches a failure nor makes the method continue after one. Each caller must catch IOException or declare it in turn. A catch can also rethrow the same object with throw e;.

Catch where a useful response is possible. A helper usually cannot ask the user to select a different file, but main can. Printing "error" and returning an empty list would confuse a missing file with a genuinely empty file. A small experiment may let main declare throws IOException; a finished program handles expected failures with useful messages. Unchecked types may be declared for documentation even though the compiler does not require them.

Respect the inherited contract

If an interface declares read() throws IOException, an override may declare IOException, a narrower checked subclass, or no checked exception. It cannot broaden the declaration to Exception. It can declare unchecked types. An override of Object.toString() cannot add IOException, since the inherited method declares no checked exceptions. Calls through the interface type must still address its declared IOException, even when one implementation declares none.

Key Takeaways

  • Use throw with an exception object to stop an invalid operation.
  • Validate before changing fields or collections.
  • throws declares a possible failure; it does not handle it.
  • Catch where meaningful recovery is possible; otherwise pass the failure to the caller.
  • Overrides cannot add new or broader checked exceptions.

3.2 Describe domain failures and preserve their causes

A standard exception is often enough. Create a custom class when callers need to recognize a problem specific to the program, such as insufficient stock or a malformed data record, and respond differently to it.

Choose the superclass deliberately

Extending Exception creates a checked exception. Extending RuntimeException creates an unchecked exception. Use the checked design when callers should plan for a recoverable domain failure; use the unchecked design for misuse or a programming bug.

class OutOfStockException extends Exception {
    public OutOfStockException(String message) {
        super(message);
    }
}

super(message) stores the message in the inherited exception machinery, so getMessage() returns it. The class name conventionally ends in Exception. Extra fields and getters can expose structured details such as requested and available counts.

Leave stock unchanged after failure
import java.util.HashMap;

class Inventory {
    private final HashMap<String, Integer> stock = new HashMap<>();

    Inventory() {
        stock.put("pens", 12);
    }

    void remove(String item, int quantity) throws OutOfStockException {
        if (quantity <= 0) {
            throw new IllegalArgumentException("quantity must be positive");
        }
        int available = stock.getOrDefault(item, 0);
        if (quantity > available) {
            throw new OutOfStockException("Requested " + quantity
                + " of " + item + ", only " + available + " in stock");
        }
        stock.put(item, available - quantity);
    }
}

Starting with 12 pens, removing 5 leaves 7. A later request for 10 throws, and 7 remain because the update comes after all checks. The caller must handle or declare the checked stock failure; the invalid-quantity failure is unchecked. A program needing a distinct unknown-item response could use a related UnknownItemException, with both domain types under an InventoryException base class.

Wrap without losing the original problem

A parser can translate a low-level conversion failure into a record-level failure:

class InvalidRecordException extends Exception {
    public InvalidRecordException(String message) {
        super(message);
    }
    public InvalidRecordException(String message, Throwable cause) {
        super(message, cause);
    }
}

Inside the parsing method, a handler can do this:

catch (NumberFormatException e) {
    throw new InvalidRecordException(
        "Line 3: quantity is not a number: x", e);
}

The wrapper gives the caller a meaningful category and line number. Its getCause() returns the original NumberFormatException, and a printed trace retains a Caused by: section. Building a new exception with only the old message loses the original object and its trace.

java.io.UncheckedIOException is a ready-made unchecked wrapper specifically for IOException. Its constructors accept the cause, with an optional message. It can carry a file failure through an override that cannot add a checked declaration. Wrapping changes the type the caller sees; it does not repair the file problem. Keep ordinary loop decisions as conditions and break, without inventing exceptions for routine flow.

Key Takeaways

  • Custom classes let callers recognize meaningful domain failures.
  • Extend Exception for a checked class or RuntimeException for an unchecked class.
  • Call super(message) to retain a useful diagnostic.
  • Validate the entire request before updating state.
  • Pass the original exception as a cause when wrapping it.
  • UncheckedIOException carries an IOException as an unchecked failure.
4

Locate files and close resources safely

A text file must be found, decoded, and closed correctly. A relative path depends on the working directory, while bytes become readable characters only through the right encoding. Numeric text and line endings introduce their own portability choices. Once a file is open, try-with-resources releases it on every exit and keeps the main failure visible if closing also fails. These choices make later reading and writing code easier to trust.

4.1 Make text files work across computers

A file stores bytes, while your program works with characters and numbers. A successful read needs the right location, the right character encoding, and a clear convention for lines and numeric text.

Find the actual location

A relative path starts from the program's working directory. It does not start from the folder holding the source code. An absolute path starts from the file-system root, such as /home/ana/data/scores.txt, or a drive root on Windows.

Path file = Path.of("data", "scores.txt");
System.out.println(System.getProperty("user.dir"));
System.out.println(file.toAbsolutePath());
System.out.println(file.getFileName());

Import java.nio.file.Path. Creating this Path opens nothing and checks no existence. toAbsolutePath() reveals where Java will look, and getFileName() gives scores.txt. An IDE often uses the project folder as the working directory. Forward slashes in "data/scores.txt" work on Windows, Linux and macOS. A Windows path literal using backslashes needs escaping, as in "C:\\data\\scores.txt". The older java.io.File represents a location too; convert with toPath() or toFile().

Match bytes to characters

UTF-8 encodes every Unicode character. Basic Latin characters take one byte; others take two to four. The text "café" contains four characters but five UTF-8 bytes because "é" takes two. Reading those bytes as ISO-8859-1 can produce "café". Use the encoding the writer used.

The text methods of Files default to UTF-8. Classes such as FileWriter and a scanner opened without a charset use the default charset, which became UTF-8 in Java 18; older installations can differ. StandardCharsets.UTF_8, from java.nio.charset, makes the choice explicit. Invalid bytes read by Files.readAllLines produce MalformedInputException, an IOException subclass.

Read lines without leftover endings
ConventionJava string escape
Linux and macOS line ending\n
Typical Windows line ending\r\n

With a terminator after each line, "a" and "b" need four bytes with LF endings and six with CRLF endings. BufferedReader.readLine(), Files.readAllLines, and Scanner.nextLine() remove recognized line endings. Splitting a complete string with split("\n") leaves the Windows \r, so converting "12\r" with parseInt fails. Prefer line-reading methods, or trim the text. System.lineSeparator() and formatting %n produce the current system's ending.

Keep numeric files consistent

Integer.parseInt accepts integer text, with no decimal separator. Double.parseDouble("3.5") accepts a period; Double.parseDouble("3,5") fails. These parsing methods ignore locale. Scanner numeric methods and ordinary decimal formatting follow locale, so German or Dutch settings may expect "3,5" and produce "3,50". Use scanner.useLocale(Locale.ROOT) and String.format(Locale.ROOT, "%.2f", value) for period-decimal data; import java.util.Locale.

Missing locations commonly produce NoSuchFileException with Files or Scanner(Path), while older file-name constructors can give FileNotFoundException. Permission failures can give AccessDeniedException. These are checked I/O failures: a correct path expression alone cannot prevent them.

Key Takeaways

  • Relative paths are resolved from the working directory.
  • Creating a Path does not open or check the file.
  • Match reading and writing encodings; choose UTF-8 explicitly where defaults can vary.
  • Line-reading methods remove LF, CRLF, and CR terminators.
  • Double.parseDouble uses a period; locale-sensitive numeric methods need a chosen locale.
  • Opening and reading files still require checked-exception handling.

4.2 Let Java close every opened resource

An open file uses an operating-system resource. Closing releases it and flushes a writer's pending output. A forgotten close can exhaust open-file limits, lose buffered text, or leave another program unable to change the file.

Declare resources in the try header
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

class Lines {
    static void show(Path file) throws IOException {
        try (BufferedReader in =
                Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
            String line;
            while ((line = in.readLine()) != null) {
                System.out.println(line);
            }
        }
    }
}

The header opens the reader. The body uses it, and Java closes it when the body ends normally, returns, or throws. No separate finally is needed. There is no handler here, so any checked failure still passes to the caller through throws IOException.

A resource must implement AutoCloseable. That interface declares close() and permits Exception; its Closeable subinterface narrows the declared checked failure to IOException. Readers, writers, and Scanner qualify. A String does not. Header variables are implicitly final and are available in the body, not in that statement's catch or finally blocks. Java 9 and later also allow an existing final or effectively final variable: try (in) { ... }.

Close in reverse order

Separate resources with semicolons:

try (BufferedReader in = Files.newBufferedReader(source);
     java.io.BufferedWriter out = Files.newBufferedWriter(target)) {
    String line;
    while ((line = in.readLine()) != null) {
        out.write(line);
        out.newLine();
    }
}

This is a block inside a method declaring IOException, with distinct source and target paths. Java opens in first, then out, and closes out before in. If opening out fails, the already-open reader is still closed. Opening a writer on the input path would truncate that input, so the paths must differ for this direct copy.

Resource closing happens before catch and finally clauses belonging to the same statement. Those handlers can receive failures from opening, using, or closing the resources.

Keep the main failure visible

Suppose the body throws a record exception, then closing the reader throws an IOException. Try-with-resources propagates the body exception and attaches the closing failure as suppressed. getSuppressed() retrieves it, and the trace prints a Suppressed: section. The original body failure stays visible. If the body succeeds and closing alone fails, the closing exception propagates normally.

With multiple failures during closing, Java still attempts the remaining closes. A plain finally { resource.close(); } can instead replace a pending body failure with a cleanup failure.

Use this pattern for file resources your code owns. Closing a scanner on System.in also closes the program's keyboard input, preventing later reads. Keep ownership of shared standard input at the program level instead of closing it in a helper.

Key Takeaways

  • Try-with-resources closes successfully opened resources on normal and exceptional exits.
  • Only AutoCloseable objects qualify as resources.
  • Resources open left to right and close right to left.
  • Closing precedes the same statement's catch and finally blocks.
  • A body failure stays primary; later closing failures are suppressed.
  • Automatic closing does not replace catch-or-declare handling.
  • Closing a scanner also closes its closeable input source.
5

Read and write text files

File processing connects external bytes to the objects and results your program uses. Read lines with a method suited to the input size, validate fields before conversion, and write with a deliberate replacement or append policy. A complete report needs separate responses for a bad record and an unusable file. Build the result before saving it, then use temporary output and a supported atomic move when an existing destination must be protected.

5.1 Read lines and turn them into objects

Reading gives you text. Parsing gives that text a meaning: a count, an age, or an object. Keep those two operations separate so a bad record does not look like a failed file read.

Choose how much to hold in memory
MethodResult and use
Files.readAllLines(path)A list containing every line; convenient for small files
Files.readString(path)One string retaining line endings
BufferedReader.readLine()One line at a time; null signals the end
Scanner.hasNextLine() / nextLine()Convenient line-by-line reading

Import java.nio.file.Files and Path, plus the reader or collection types you use. Files text methods default to UTF-8. A BufferedReader belongs in try-with-resources and reports reading failures with IOException. Reading one line at a time avoids holding the entire input in memory, unless your processing stores all the records afterward.

A scanner also needs closing, and one extra failure check:

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Scanner;

class ScanFile {
    static void show(Path file) throws IOException {
        try (Scanner sc = new Scanner(file, StandardCharsets.UTF_8)) {
            while (sc.hasNextLine()) {
                System.out.println(sc.nextLine());
            }
            if (sc.ioException() != null) throw sc.ioException();
        }
    }
}

Opening can throw directly. During reading, Scanner treats an underlying I/O failure as end of input and stores it; ioException() exposes it. Without that final check, a partial read can look successful.

Count physical lines, then parse

For input lines "12", "15", "abc", an empty line, and "9", increment the line number before deciding whether to skip a blank. Convert each nonblank line with Integer.parseInt(line.trim()) inside its own try. Report "Line 3: not a number: abc" and continue. The valid sum is 36 and count is 3, giving average 12.0. Compute (double) sum / count to preserve a fractional result, and check that the count is not zero first.

Check fields before indexing

Simple comma-separated data can become objects. Here the first line is a required header; each remaining record has a nonempty name and integer age:

String[] parts = line.split(",", -1);
if (parts.length != 2 || parts[0].isBlank() || parts[1].isBlank()) {
    System.out.println("Line " + lineNumber + ": expected name and age");
    continue;
}
try {
    int age = Integer.parseInt(parts[1].trim());
    people.add(new Person(parts[0].trim(), age));
} catch (NumberFormatException e) {
    System.out.println("Line " + lineNumber + ": invalid age");
}

This loop-body fragment assumes line, lineNumber, a List<Person> named people, and a Person(String, int) constructor. Skip the header "name,age" before this parsing step; otherwise "age" fails numeric conversion. The records "Ana,34", "Ben,29", and "Chen,41" total 104 years and average about 34.67.

Plain split(",") drops trailing empty fields: "Eve," produces only one part. The -1 limit keeps the empty second field so validation can report it. Always check length before parts[1]. Splitting alone does not handle quoted commas, such as the name in ""Smith, Ana",34"; full CSV needs a CSV parser.

Key Takeaways

  • Choose whole-file methods for manageable inputs or a reader loop for large ones.
  • Check Scanner.ioException() after reading to detect a hidden read failure.
  • Count original file lines even when blanks or records are skipped.
  • Check field count and required values before indexing and converting.
  • Skip a header before parsing records.
  • Plain splitting cannot parse quoted CSV fields.

5.2 Write complete text and append deliberately

Opening an output file can change it immediately. Choose replacement or appending before opening the writer, and finish by closing it so buffered output is not left in memory.

Replace or append

Files.writeString(path, text) writes one string. Files.write(path, lines) writes an iterable of lines, adding the system line separator after each, including the last. With their default options, both create a missing file and truncate an existing one.

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

class RunLog {
    static void recordStart(Path log) throws IOException {
        Files.writeString(log, "started" + System.lineSeparator(),
            StandardCharsets.UTF_8,
            StandardOpenOption.CREATE, StandardOpenOption.APPEND);
    }
}

CREATE allows a new file; APPEND preserves old content and adds at the end. APPEND alone fails if the file is absent. Appending does not insert a missing separator before your text: if an existing file ends halfway through a line, the next characters continue that line.

The older FileWriter has an append flag: new FileWriter("log.txt", StandardCharsets.UTF_8, true). Without append, a new FileWriter or a file-name PrintWriter truncates an existing file too. Never open a replacing writer on input you still need to read.

Choose a writer and notice failures

BufferedWriter supports write and newLine(), and reports write failures as checked exceptions:

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Locale;

class ReportWriter {
    static void write(Path file) throws IOException {
        try (BufferedWriter out =
                Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
            out.write("Readings: 3");
            out.newLine();
            out.write(String.format(Locale.ROOT, "Average: %.2f", 3.0));
            out.newLine();
        }
    }
}

The file has two lines: "Readings: 3" and "Average: 3.00". Locale.ROOT fixes the decimal point. newLine(), println, and %n all use the platform line ending; a literal \n writes LF on every system.

A PrintWriter offers convenient print, println, and printf, but those methods record I/O failures instead of throwing them. checkError() flushes and reports its error flag. When checking final close failures too, retain access to the writer and check after closing. For code that must reliably propagate writing failures, use BufferedWriter or the Files methods.

Complete the round trip

Writers buffer output. flush() sends pending text onward; close() flushes and releases the file. Try-with-resources ensures closing is attempted on every exit, but cannot make a disk write succeed.

To save a person, write the name, a comma, and the integer age, then a line ending. Format decimals with Locale.ROOT, so a later Double.parseDouble can read them. A missing parent directory is not created by opening a file: use Files.createDirectories(folder) when creating it is intended, or report the failure. A write can fail after truncation or partial output; use temporary output and an atomic move when the destination must be protected.

Key Takeaways

  • Default writing creates a missing file and truncates an existing one.
  • Use CREATE with APPEND to retain old content and allow a new log.
  • Closing flushes buffered output and releases the resource.
  • PrintWriter records write errors; checkError() exposes them.
  • BufferedWriter and Files methods propagate I/O failures.
  • Use UTF-8 and Locale.ROOT for a portable text round trip.
  • Writing a file does not create missing parent folders.

5.3 Build a report without hiding failures

A robust file processor needs two recovery levels. A bad record can be skipped and reported; a failure to read or save the file stops the task. Compute a complete result before touching its destination.

Read, validate, compute, save

The complete program below reads optional header "date,temperature" followed by simple two-field records. Dates are nonempty labels; temperatures are finite numbers in degrees Celsius. It skips and reports malformed records, including blank lines. The nested checked exception keeps record problems separate from file problems.

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Locale;

public class TemperatureReport {
    static class InvalidRecordException extends Exception {
        InvalidRecordException(String message) { super(message); }
        InvalidRecordException(String message, Throwable cause) {
            super(message, cause);
        }
    }

    static List<String> readLines(Path file) throws IOException {
        return Files.readAllLines(file, StandardCharsets.UTF_8);
    }

    static double parseTemperature(String line, int lineNumber)
            throws InvalidRecordException {
        String[] parts = line.split(",", -1);
        if (parts.length != 2 || parts[0].isBlank()
                || parts[1].isBlank()) {
            throw new InvalidRecordException("Line " + lineNumber
                + ": expected a date label and a temperature");
        }
        try {
            double value = Double.parseDouble(parts[1].trim());
            if (!Double.isFinite(value)) {
                throw new InvalidRecordException("Line " + lineNumber
                    + ": temperature must be finite");
            }
            return value;
        } catch (NumberFormatException e) {
            throw new InvalidRecordException("Line " + lineNumber
                + ": not a number: " + parts[1], e);
        }
    }

    static String summarize(List<String> lines) {
        int count = 0;
        int skipped = 0;
        double sum = 0;
        double min = Double.POSITIVE_INFINITY;
        double max = Double.NEGATIVE_INFINITY;
        for (int i = 0; i < lines.size(); i++) {
            String line = lines.get(i);
            if (i == 0 && line.equals("date,temperature")) continue;
            try {
                double value = parseTemperature(line, i + 1);
                sum += value;
                count++;
                min = Math.min(min, value);
                max = Math.max(max, value);
            } catch (InvalidRecordException e) {
                skipped++;
                System.err.println(e.getMessage());
            }
        }
        if (count == 0) {
            return String.format(Locale.ROOT,
                "No valid readings%nSkipped lines: %d%n", skipped);
        }
        return String.format(Locale.ROOT,
            "Valid readings: %d%nAverage (°C): %.2f%n"
                + "Minimum (°C): %.2f%nMaximum (°C): %.2f%n"
                + "Skipped lines: %d%n",
            count, sum / count, min, max, skipped);
    }

    static void writeSummary(Path file, String text) throws IOException {
        Path target = file.toAbsolutePath();
        Path temp = Files.createTempFile(target.getParent(), "report-", ".tmp");
        try {
            Files.writeString(temp, text, StandardCharsets.UTF_8);
            Files.move(temp, target, StandardCopyOption.ATOMIC_MOVE);
        } catch (IOException e) {
            try {
                Files.deleteIfExists(temp);
            } catch (IOException cleanup) {
                e.addSuppressed(cleanup);
            }
            throw e;
        }
    }

    public static void main(String[] args) {
        Path input = Path.of("readings.csv");
        Path output = Path.of("summary.txt");
        try {
            List<String> lines = readLines(input);
            String report = summarize(lines);
            writeSummary(output, report);
            System.out.println("Saved: " + output.toAbsolutePath());
        } catch (NoSuchFileException e) {
            System.err.println("File or folder not found: " + e.getFile());
        } catch (AtomicMoveNotSupportedException e) {
            System.err.println("Could not save atomically: "
                + output.toAbsolutePath());
        } catch (IOException e) {
            System.err.println("Could not process " + input.toAbsolutePath()
                + " or save " + output.toAbsolutePath() + ": " + e.getMessage());
        }
    }
}
Follow one run

Use these five input lines without a header:

2026-03-01,4.5
2026-03-02,6.0
2026-03-03,abc
2026-03-04,-1.5
missing comma

Lines 1, 2, and 4 produce three valid readings. The sum is 9.0; average is 3.00 °C, minimum is -1.50 °C, and maximum is 6.00 °C. Lines 3 and 5 produce diagnostics, and the report records two skipped lines. The parsing handler sits inside the loop, so each bad record leaves later records reachable. Updating totals only after successful parsing keeps rejected values out.

Double.parseDouble accepts special strings such as "NaN" and "Infinity". Double.isFinite rejects them here because they cannot serve as ordinary measured temperatures. An empty file, a header-only file, or all-invalid records reaches the count-zero branch before division or use of the initial minimum and maximum.

Protect the destination

The read and computation finish before saving begins. Files.writeString opens and closes its own file, but can fail after writing part of it. The program therefore writes to a temporary file in the destination folder, closes it, and requests ATOMIC_MOVE. The move makes the finished result visible as one file-system operation when supported.

Replacing an existing target atomically is implementation dependent. The program reports an unsupported move or replacement and never retries with a non-atomic move. A cleanup failure is attached to the original exception instead of replacing it. Atomic visibility does not promise survival of a power loss.

Checking Files.exists(input) beforehand cannot guarantee the later read: a file can disappear or become inaccessible after the check. Handle the actual operation. Before relying on a processor, try missing input, missing output folders, empty and header-only files, CRLF endings, accented text, and malformed records. User messages should name the failed path; debugging a wrapper also needs its original cause and stack trace.

Key Takeaways

  • Handle record failures inside the loop and whole-file failures outside it.
  • Validate a complete record before updating counts or totals.
  • Check for zero valid records before computing an average.
  • Finish reading and computation before opening output.
  • Write and close a temporary file, then request an atomic move to protect the destination.
  • Report unsupported atomic replacement instead of silently falling back.
  • Keep original causes and cleanup failures available for diagnosis.

Exceptions and Files in Java examples

5 Walkthroughs

1

Follow a failure back to its cause

11 steps
Read an exception trace, connect it to the active calls, and use inheritance to classify the failure.
  1. 1
    IntroductionA program can compile and still fail

    An input value can make valid Java code fail while it runs. The exception object tells you what kind of problem occurred, and the stack trace shows which method calls were active.

    Follow a failed integer conversion first. Then use the same inheritance rules that make subclass objects usable as superclass objects to decide what the compiler requires you to handle.

  2. 2
    ExampleWatch the conversion stop

    A method loadCount executes these statements:

    System.out.print("start ");
    int count = Integer.parseInt("eight");
    System.out.print("finish");
    

    It prints start , then throws NumberFormatException. The assignment does not complete, and finish is skipped. A matching handler can take over, but the failed statement does not resume after recovery.

  3. 3
    ExplanationFollow the active calls

    Suppose main called loadCount, which called Integer.parseInt. Those calls form part of the call stack. The exception moves outward when a method has no matching handler.

    parseInt fails first, loadCount cannot finish its normal work, and the caller gets a chance to handle the failure. If it leaves main unhandled, Java reports the exception and the main thread ends.

  4. 4
    ExampleFind your first frame

    A trace can include these application frames after Java's library frames:

    at Counts.loadCount(Counts.java:14)
    at Counts.main(Counts.java:5)
    

    Inspect line 14 first: that is the call in your code nearest to the detection point. Line 5 tells you where loadCount was called. The exception's first line gives its class and message; do not confuse the lower caller frame with the statement that first used the bad text.

  5. 5
    ChallengeFind the skipped output

    A helper prints A, calls Integer.parseInt("q2"), then would print B. Its caller catches NumberFormatException and prints C. What letters print, and why?

    ---reveal---

    A then C. The conversion throws before B; propagation takes the failure to the caller's matching handler. The helper's remaining statements are abandoned, so recovery does not return to print B.

  6. 6
    TipLook beyond the detected statement

    The statement where a failure is detected may be using a bad value created earlier. A null-reference failure tells you to trace where that reference should have received an object.

    Use getMessage() for diagnostic text and printStackTrace() for the call chain. A message can be null; a Caused by: section supplies another exception retained inside a wrapper.

  7. 7
    ExplanationUse the superclass chain

    Throwable is the base class for throwable objects. Its main branches are Error and Exception; RuntimeException sits under Exception.

    RuntimeException, Error, and every subclass of either are unchecked. Other Throwable subclasses are checked. Both categories fail during execution; "checked" describes the compiler's check of handling, not a different time when the exception is thrown.

  8. 8
    ExampleCompare a parser and a file reader

    NumberFormatException extends IllegalArgumentException, then RuntimeException, so a call to Integer.parseInt has no compulsory handler.

    IOException extends Exception outside that branch. A call to Files.readString must catch its possible IOException or declare it with throws. A file can fail for external reasons even when the calling code is correct.

  9. 9
    ChallengeClassify an unfamiliar failure

    BadRecordException extends Exception directly. A helper declares that it may throw this type. What must its caller do, and when is that obligation checked?

    ---reveal---

    Catch it or declare an applicable checked type in the caller's method declaration. The compiler enforces that obligation because the class is outside the unchecked branches. Whether one particular run succeeds does not remove the declaration-level requirement.

  10. 10
    ChallengeExplain a surprisingly broad handler

    A file-reading block catches Exception and prints "File problem". It instead fails with a NullPointerException caused by a bug. Will the handler receive it, and is that message reliable?

    ---reveal---

    Yes: NullPointerException extends RuntimeException, which extends Exception. The message is misleading because this failure is a code bug, not evidence of a file problem. Read the trace and narrow the expected handler to the failures it can explain.

  11. 11
    RecapChoose the next debugging action

    Start a failure investigation with its class, message, and first application frame. Follow callers and the origin of bad values when the detected statement alone does not explain the cause.

    Then check inheritance before choosing handling: checked failures require a compiler-visible decision; unchecked bugs still need correction. Keep broad handlers from disguising one kind of problem as another.

2

Trace recovery and cleanup paths

12 steps
Follow a failed input conversion, choose the scope and order of handlers, and trace finally on early exits.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionDecide what should happen next
  2. 2
    ExampleRecover after the whole statement
  3. 3
    TipMake a retry read new text
  4. 4
    ChallengeRepair the stuck scanner
  5. 5
    ExplanationGive a specific failure its own response
  6. 6
    ExampleLet the loop continue
  7. 7
    ChallengeMove the protected boundary
  8. 8
    Key InsightShare responses without overlapping types
  9. 9
    ExplanationCleanup runs before leaving
  10. 10
    ChallengeTrace an unmatched failure
  11. 11
    ChallengeKeep cleanup from hiding a retry failure
  12. 12
    RecapTrace the next reachable statement
3

Reject a request without damaging state

11 steps
Validate an inventory operation, expose a domain failure, and wrap a parsing failure while keeping its cause.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionPreserve a usable object
  2. 2
    ExampleValidate before subtraction
  3. 3
    ExplanationSeparate throw from the declaration
  4. 4
    ChallengeChoose the right standard failure
  5. 5
    ConnectionAn override keeps promises to callers
  6. 6
    ExampleGive insufficient stock its own type
  7. 7
    ExampleKeep the failed request separate
  8. 8
    ChallengeDecide what state survives
  9. 9
    ExplanationRetain the original conversion failure
  10. 10
    ChallengePass a file failure through a restricted method
  11. 11
    RecapDesign an exception the caller can use
4

Open the right text and close it safely

12 steps
Resolve a path, match text conventions, then trace resource opening, closing, and competing failures.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionLocation and lifetime both matter
  2. 2
    ExampleResolve from the working directory
  3. 3
    ExplanationDecode with the writer's charset
  4. 4
    TipRemove a complete line ending
  5. 5
    ChallengeMake a decimal survive the round trip
  6. 6
    ExplanationDeclare a resource to close
  7. 7
    ConnectionUse the closing contract
  8. 8
    ExampleReverse the opening order
  9. 9
    ChallengeTrace a failed second opening
  10. 10
    Key InsightKeep a body failure as the main report
  11. 11
    ChallengeSeparate data failure from cleanup failure
  12. 12
    RecapInspect a file operation in order
5

Turn readings into a dependable report

16 steps
Read and validate simple records, compute accepted results, and save completed output with a clear failure policy.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionA report needs more than correct arithmetic
  2. 2
    ExplanationChoose how lines arrive
  3. 3
    ExampleDefine the record before parsing
  4. 4
    ExampleValidate before using the second field
  5. 5
    ChallengeLocate the rejected record
  6. 6
    ExplanationChoose replacement or appending
  7. 7
    ExampleWrite a portable report line
  8. 8
    TipNotice a write that failed
  9. 9
    ChallengeKeep both old and new log entries
  10. 10
    ConnectionRecover at two different levels
  11. 11
    ExampleUpdate totals only after validation
  12. 12
    ChallengeHandle a value that parses but cannot serve
  13. 13
    ExplanationFinish output before replacing the target
  14. 14
    TipKeep the save failure visible
  15. 15
    ChallengeChoose what can safely be reported
  16. 16
    RecapReview the processor by failure path

Exceptions and Files in Java practice questions

40 Practice Questions in 4 sets

Set 1: Trace failures and choose useful recovery10 Practice Questions

Question 1 of 10

An array has length 5. What happens when the program evaluates values[5]?
  1. It reads the fifth element of the array.
  2. It throws ArrayIndexOutOfBoundsException.
  3. It returns the default integer value 0.
  4. It throws NumberFormatException.
Show answerHide answer
Answer: B
An array of length 5 has valid indexes 0 through 4, so index 5 is outside it. Java throws ArrayIndexOutOfBoundsException at that access. Counting five elements does not make index 5 valid: the fifth element is at index 4.

Question 2 of 10

DataProblem extends Exception directly. What obligation does a method have when it calls a helper declared throws DataProblem?
  1. Catch RuntimeException or declare it.
  2. Declare it only if the helper actually fails.
  3. Handle it only when the program runs.
  4. Catch DataProblem or declare it.
Show answerHide answer
Answer: D
DataProblem is checked because it extends Exception outside the RuntimeException branch. The calling code must catch it or declare an applicable checked type. The compiler checks the declared possibility, even if a particular call would succeed.

Question 3 of 10

What letters print, in order?

System.out.print("P");
try {
    int n = Integer.parseInt("7q");
    System.out.print("Q");
} catch (NumberFormatException e) {
    System.out.print("R");
}
System.out.print("S");
  1. PRS
  2. PQRS
  3. PR
  4. PS
Show answerHide answer
Answer: A
Converting "7q" throws NumberFormatException before the statement printing Q. The matching handler prints R, then execution continues after the statement and prints S. The skipped statement does not run after recovery, so PQRS cannot be the output.

Question 4 of 10

A block may throw NoSuchFileException or another IOException. What catch order gives each its own response?
  1. IOException, then NoSuchFileException.
  2. Exception, then NoSuchFileException.
  3. NoSuchFileException, then IOException.
  4. IOException | NoSuchFileException in one clause.
Show answerHide answer
Answer: C
NoSuchFileException extends IOException, so its specific handler must appear first. Putting IOException first would already catch every missing-file exception and make the later handler unreachable. A multi-catch cannot combine these related types either.

Question 5 of 10

What does calling pick() print and return?

static int pick() {
    try {
        return 8;
    } finally {
        System.out.print("done");
    }
}
  1. It returns 8 without printing anything.
  2. It prints done and returns 8.
  3. It prints done and returns no value.
  4. It prints 8 and then returns done.
Show answerHide answer
Answer: B
The return expression is evaluated, but the method runs finally before delivering that value to its caller. It therefore prints done and returns 8. A return inside try does not bypass cleanup; only a competing transfer from cleanup would replace that result.

Question 6 of 10

A method rejects a negative capacity before assigning it to a field. What standard exception best describes the invalid argument?
  1. IllegalArgumentException
  2. IllegalStateException
  3. NumberFormatException
  4. UnsupportedOperationException
Show answerHide answer
Answer: A
A negative capacity violates the method's argument rule, so IllegalArgumentException describes the failure. IllegalStateException would describe a call forbidden by the object's current state. No parsing operation is stated, so a numeric argument alone does not make this a number-format failure.

Question 7 of 10

A program starts with working directory /work/app. It creates Path.of("data", "levels.txt"). What absolute location does that relative path identify?
  1. /work/data/levels.txt
  2. /data/levels.txt
  3. /work/app/src/data/levels.txt
  4. /work/app/data/levels.txt
Show answerHide answer
Answer: D
A relative path starts at the working directory, so the two path elements extend /work/app to /work/app/data/levels.txt. Java does not insert a source folder. Placing the file beside source code would work only if that happened to be the location the resolved path names.

Question 8 of 10

Resource a opens, but opening resource b throws. Both are declared in the same try-with-resources header, in that order. Closing a also throws. Which failure reaches the caller?
  1. The closing failure, with the opening failure suppressed.
  2. The opening failure, with the closing failure discarded.
  3. The opening failure, with the closing failure suppressed.
  4. Both failures separately, in their order of occurrence.
Show answerHide answer
Answer: C
When opening b fails, Java still closes the already-open a. The opening failure stays primary and the later closing failure is attached as suppressed. Choosing the closing failure as primary confuses try-with-resources with manual cleanup that can overwrite an earlier failure.

Question 9 of 10

A BufferedReader has reached the end of its file. What does the next readLine() return?
  1. null
  2. An empty string.
  3. A string containing "EOF".
  4. A string containing "\n".
Show answerHide answer
Answer: A
BufferedReader.readLine() returns null when no characters remain to form another line. An empty string represents a real blank line, so using it as the end marker would stop too soon. Line terminators are removed from returned lines and are not an end-of-file marker.

Question 10 of 10

A UTF-8 log may already exist or may be missing. Which options let Files.writeString preserve any existing text and add new text at the end?
  1. CREATE and TRUNCATE_EXISTING
  2. CREATE and APPEND
  3. APPEND without CREATE
  4. CREATE_NEW and WRITE
Show answerHide answer
Answer: B
APPEND writes after existing content, and CREATE permits a missing file to be created. Using only APPEND fails when the log does not exist. TRUNCATE_EXISTING would erase existing content, while CREATE_NEW rejects a path that already exists.
Set 2: Apply contracts to records and file output10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A trace begins with these frames. Which line in the learner's class should be inspected first?

java.lang.NumberFormatException: For input string: "six"
    at java.base/java.lang.NumberFormatException.forInputString(...)
    at java.base/java.lang.Integer.parseInt(...)
    at Importer.readCount(Importer.java:18)
    at Importer.main(Importer.java:6)
  1. Line 6 in Importer.main.
  2. The library frame in forInputString.
  3. Line 18 in Importer.readCount.
  4. The line after line 18 in Importer.
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

AmountProblem extends IllegalArgumentException. How is it classified?
  1. Unchecked, through RuntimeException.
  2. Checked, because it is a custom class.
  3. Checked, because its parent is an exception.
  4. Unchecked, through the Error branch.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A retry loop catches InputMismatchException from Scanner.nextInt(), prints a message, and immediately calls nextInt() again. The next token is "many". Why does the loop keep failing?
  1. The handler rewinds the entire input stream.
  2. The scanner converts the token to zero.
  3. The exception permanently closes the scanner.
  4. The failed read leaves the same token unread.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

An interface declares void load() throws IOException. An implementation needs to declare a missing-file failure. Which checked declaration is allowed on its override?
  1. throws Exception
  2. throws NoSuchFileException
  3. throws Throwable
  4. throws InterruptedException
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

An inventory contains 17 markers. Its remove method rejects requests larger than the current stock before changing the map. Calls remove 6, then request 14; the second failure is wrapped with its cause and caught by the caller. What stock and diagnostic information remain?
  1. 11 markers but only the wrapper's new message.
  2. -3 markers and the original failure as the cause.
  3. 11 markers and the original failure as the cause.
  4. 17 markers and the original failure as the cause.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

What happens when Double.parseDouble("6,25") runs on a computer using German locale settings?
  1. It returns the decimal value 6.25.
  2. It returns the whole-number value 625.
  3. It throws MalformedInputException.
  4. It throws NumberFormatException.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

What interface must an object implement to be declared as a try-with-resources resource?
  1. AutoCloseable
  2. Serializable
  3. Iterable
  4. Comparable
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

The line is "Nora,". What difference matters between line.split(",") and line.split(",", -1)?
  1. Both return two fields, each with an empty second field.
  2. The first keeps the comma; the second removes the comma.
  3. The first returns one field; the second keeps an empty second field.
  4. The first throws; the second returns one field.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A program writes through PrintWriter, but a full disk prevents the text from being saved. What should it use to detect the writer's recorded error?
  1. Catch IOException from println itself.
  2. Call checkError() and inspect the result.
  3. Inspect the file path's getFileName().
  4. Assume closing guarantees successful saving.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A report must protect an existing result from partial replacement. Reading and computation have finished. What save policy is appropriate?
  1. Write directly to the target; retry from the start if the first write fails.
  2. Write a temporary file; use a non-atomic move if the atomic move fails.
  3. Check the target exists; append the new report after the old result.
  4. Write and close a same-folder temporary file; request an atomic move and report unsupported replacement.
Show answerHide answer

Save this lesson to see this answer.

Set 3: Trace interacting failures and cleanup10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

Which exception family also receives NumberFormatException when caught by a superclass handler?
  1. RuntimeException
  2. IOException
  3. Error
  4. FileNotFoundException
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

What value is printed?

int count;
try {
    count = Integer.parseInt("bad");
} catch (NumberFormatException e) {
    count = 4;
}
System.out.println(count + 2);
  1. 4
  2. 2
  3. 6
  4. Nothing; count is uninitialized.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

What value reaches the final print?

int total = 0;
try {
    for (String text : new String[] {"8", "bad", "3"}) {
        try {
            total += Integer.parseInt(text);
        } catch (NumberFormatException e) {
            throw new IllegalStateException("record", e);
        }
    }
} catch (IllegalStateException e) {
    total += 2;
}
System.out.println(total);
  1. 13
  2. 10
  3. 11
  4. 2
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

What does result() do?

static int result() {
    try {
        throw new IllegalArgumentException("bad");
    } finally {
        return 9;
    }
}
  1. It throws the exception and never returns 9.
  2. It returns 9, then throws the exception to the caller.
  3. It fails to compile because finally cannot return.
  4. It returns 9 and discards the pending exception.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

A parser catches NumberFormatException e. Its custom InvalidRecordException has message-only and message-plus-cause constructors. How should it add "Line 8" while retaining the original trace?
  1. throw new InvalidRecordException(e.getMessage());
  2. throw new InvalidRecordException("Line 8", e);
  3. throw new InvalidRecordException("Line 8");
  4. throw new RuntimeException("Line 8");
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A Windows text file contains integer lines terminated by CRLF. Code uses Files.readString(path).split("\n"), then Integer.parseInt on each nonempty piece. Why can a piece containing the digits "27" fail conversion?
  1. parseInt always requires a decimal point.
  2. UTF-8 cannot represent Windows line endings.
  3. The split can leave a trailing \r in the piece.
  4. The split automatically changes the digits to bytes.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

Resources a and b open successfully in that order. The body throws E; closing b throws F; closing a throws G. What reaches the catch attached to that try-with-resources statement?
  1. E, with F then G as suppressed failures.
  2. G, with E then F as suppressed failures.
  3. F, with G then E as suppressed failures.
  4. E alone because closing stops after F.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A small file starts with "name,age", followed by "Omar,36". Why should the first line be handled separately before converting the age field?
  1. It uses a different character encoding from the data.
  2. Its comma prevents split from finding two fields.
  3. A reader automatically returns it as an empty line.
  4. It names the columns instead of supplying an integer age.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A processor reads "zone,temperature" as its header, then "north,2.0", "east,bad", and "west,8.0". The required policy is to skip bad records and save a report of valid ones. A catch currently surrounds the entire parsing loop. What change achieves the policy?
  1. Keep the catch outside; resume the loop automatically after the handler.
  2. Write each total to the destination before trying to parse the next record.
  3. Catch record failures inside each iteration; save only after reading and computation finish.
  4. Return an empty result from the reader whenever parsing fails.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

Input is checked with Files.exists, then read with a scanner. Its loop ends after only some records because the underlying reader failed, and the program immediately starts saving. What must change to prevent this partial input from being treated as success?
  1. Check ioException() after scanning and stop the save when a read failure is recorded.
  2. Repeat Files.exists after scanning and save whenever it returns true.
  3. Catch only NumberFormatException around each read and then save.
  4. Close the scanner and assume its earlier reads completed the file.
Show answerHide answer

Save this lesson to see this answer.

Set 4: Diagnose and improve a complete processor10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

What prints before the exception leaves main, and which application frame is first in its trace?

public class Counter {
    static int read() {
        return Integer.parseInt("9z");
    }
    static void show() {
        System.out.print("L");
        System.out.print(read());
        System.out.print("M");
    }
    public static void main(String[] args) {
        show();
        System.out.print("N");
    }
}
  1. LM; Counter.show(Counter.java:7).
  2. Only L; Counter.main(Counter.java:11).
  3. LMN; Counter.read(Counter.java:3).
  4. Only L; Counter.read(Counter.java:3).
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A catch block reports invalid numeric input but continues with a previously assigned default value. What must be true of that default for the recovery to be useful?
  1. It must always be the integer value zero.
  2. It must be a valid value for the remaining computation.
  3. It must equal the text that failed conversion.
  4. It must be assigned inside the failed statement.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A parser uses catch (NumberFormatException | IllegalArgumentException e). Why does this multi-catch fail to compile?
  1. Neither alternative is a checked exception.
  2. The alternatives require two different variable names.
  3. One alternative is a subclass of the other.
  4. Multi-catch permits only file-related failures.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

What does choose() print and return?

static int choose() {
    int value = 5;
    try {
        return value;
    } finally {
        value = 12;
        System.out.print(value);
    }
}
  1. It prints 12 and returns 5.
  2. It prints 12 and returns 12.
  3. It prints 5 and returns 5.
  4. It prints nothing and returns 12.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

Interface ReaderTask declares String read() throws IOException. Class FixedTask implements it with public String read() and no checked declaration. Variable task has type ReaderTask and refers to a FixedTask. What must code calling task.read() do?
  1. Omit handling because the implementation declares no checked failure.
  2. Catch RuntimeException instead of the declared checked type.
  3. Add throws IOException to the implementation before calling it.
  4. Catch or declare IOException according to the interface declaration.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

An override is not allowed to add checked exceptions, but it calls file code that can throw IOException. Which standard wrapper retains that cause while exposing an unchecked failure?
  1. new IOException(e.getMessage())
  2. new UncheckedIOException(e)
  3. new Exception(e)
  4. new RuntimeException("error")
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A resource body returns 6. Its close() then throws IOException, and the attached catch returns 2; its finally block prints "closed" without throwing. What does the method do?
  1. It prints closed and returns 2.
  2. It prints closed and returns 6.
  3. It throws IOException and returns no value.
  4. It returns 6 without entering the catch.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A file has header "label,count", then "oak,7", "ash,", "elm,11", and "fir,x". The processor skips the header, retains empty split fields, validates both fields, and catches record failures inside the loop. What valid count, sum, and rejected physical line numbers result?
  1. 3 records, sum 18; reject only line 5.
  2. 1 record, sum 7; reject lines 3, 4, and 5.
  3. 2 records, sum 18; reject lines 3 and 5.
  4. 2 records, sum 18; reject lines 2 and 4.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A UTF-8 data file must contain one line "sample,7.50", readable with Double.parseDouble for its second field on computers using any locale. Which writing approach meets that format?
  1. Write "sample," + String.format("%.2f", 7.5) and a line ending.
  2. Write "sample," + String.format(Locale.ROOT, "%.2f", 7.5) and a line ending.
  3. Write "sample," + String.format(Locale.GERMANY, "%.2f", 7.5) and a line ending.
  4. Write "sample," + Integer.toString((int) 7.5) and a line ending.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A processor reads a valid header and three invalid records. It must report accepted data and skipped records, and protect an existing report from partial replacement. What result and save sequence fit?
  1. Report no valid readings and three skips; move temporary output to the target before closing its writer.
  2. Report no valid readings and four skips; close temporary output and request atomic replacement.
  3. Report no valid readings and three skips; replace the target directly, then flush and close its writer.
  4. Report no valid readings and three skips; close temporary output and request atomic replacement.
Show answerHide answer

Save this lesson to see this answer.

Stuck on your own question? Homework Help

Key Terms

64 Key Terms, each with its definition

A

Absolute path
An absolute path specifies a location from the file-system root, including a drive root where needed, independently of the working directory.
Calling toAbsolutePath() shows the absolute path used to diagnose a file placed in the wrong folder.
Appending
Appending adds new output at the end of an existing file while retaining the characters already stored there.
Appending a log entry preserves earlier entries but does not insert a missing separator before the new text.
ArithmeticException
An ArithmeticException is an unchecked exception indicating an exceptional arithmetic condition, such as integer division by zero.
Computing an integer average with an empty array can throw ArithmeticException at the division.
Atomic move
An atomic move changes a file's location as one file-system operation when supported; replacement of an existing target is implementation dependent.
An atomic move publishes a completed report all together, and unsupported replacement is reported as a save failure.
AutoCloseable
AutoCloseable is the interface declaring close that makes an object eligible for automatic closing by a try-with-resources statement.
A helper class implementing AutoCloseable can print its name when automatic cleanup calls close().

B

Buffer
A buffer is an area of memory holding text temporarily before it is sent onward to a file, reducing many small output operations.
A writer's buffer may still hold the last report line until it is flushed or the writer closes.
BufferedReader
A BufferedReader reads character input efficiently using a buffer and can return one line at a time without its line ending.
A BufferedReader loop processes a large input until readLine() returns null at the end.
BufferedWriter
A BufferedWriter writes character output through a buffer, offers line-ending support, and reports I/O failures with IOException.
A BufferedWriter writes a report line and then uses newLine() to add the platform line ending.

C

Call stack
The call stack is the chain of method calls currently active in a thread, with each call waiting for the work it requested.
When main calls load, which calls parse, the call stack records all three active method calls.
catch clause
A catch clause names a throwable type and a handler that runs when an exception from the protected work matches that type.
A catch clause for NumberFormatException can ask for another number after the user types "many".
Catch order
Catch order is the top-to-bottom sequence in which handlers are tested, requiring a subclass handler to precede a superclass handler.
Catch order puts NoSuchFileException before IOException when each needs a separate message.
Catch-or-declare rule
The catch-or-declare rule requires code that can throw a checked exception to handle it or list an applicable type in its method declaration.
The catch-or-declare rule applies to a method calling Files.readString, even when the file it reads exists.
Cause
A cause is the original throwable retained inside a wrapper exception and available through getCause for diagnosis.
The cause of an InvalidRecordException can be the NumberFormatException raised by its numeric field.
Character encoding
A character encoding maps text characters to stored bytes and specifies how a reader interprets those bytes back into text.
A mismatched character encoding can display UTF-8 text "café" as garbled text such as "café".
Checked exception
A checked exception is a Throwable subtype outside the RuntimeException and Error branches that requires catch-or-declare handling.
An IOException is a checked exception, so a file-reading helper must catch it or declare it.
Cleanup
Cleanup is work that releases resources or restores a setting when an operation ends, including paths that leave because of a failure.
Cleanup closes an opened file even when converting one of its records throws an exception.
Closeable
Closeable is an AutoCloseable subinterface for I/O resources whose close method declares IOException instead of the broader Exception.
A BufferedReader implements Closeable, so it qualifies for a try-with-resources declaration.
CSV
CSV is comma-separated values text, usually storing one record per line; quoted fields can contain commas and require proper CSV parsing.
Simple CSV containing "Mina,28" can be split, while a quoted comma in a name needs a CSV parser.
Custom exception
A custom exception is an application-defined throwable class that lets callers recognize and handle a meaningful domain failure.
An inventory uses a custom exception to distinguish insufficient stock from an invalid argument.

E

Error
An Error is a Throwable subtype for serious runtime or environment failures that ordinary application recovery should not try to catch.
OutOfMemoryError belongs to Error; catching ordinary invalid input does not address an exhausted heap.
Exception
An exception is an object describing an event that interrupts a running program and transfers control toward a matching handler.
An exception from parsing "red" stops the assignment before the program can use its numeric result.
Exception chaining
Exception chaining retains an original exception as the cause of a new exception that adds a more useful type or diagnostic context.
Exception chaining adds the failed record's line number without losing the original conversion trace.
Exception hierarchy
An exception hierarchy is an inheritance structure that lets callers catch a specific failure or a common superclass of related failures.
An exception hierarchy can place unknown-item and insufficient-stock failures under one inventory base type.
Exception masking
Exception masking occurs when a later control transfer replaces an earlier failure, hiding the original exception from the caller.
A return in finally can cause exception masking by discarding a failure raised in the try block.

F

Failing fast
Failing fast means rejecting invalid input or state at the point it is detected, before later work can spread or obscure the problem.
Failing fast in a setter checks an invalid percentage before assigning anything to the field.
Field
A field is one value within a structured record, such as the name or age separated by a comma in a simple text-data line.
The second field in "Mina," is empty when splitting with a negative limit that retains trailing empties.
finally block
A finally block is cleanup code run as control leaves its try statement, including after normal work, a handler, a return, or a thrown exception.
The finally block prints a cleanup message before a value prepared by return reaches the caller.
Flushing
Flushing sends output waiting in a writer's buffer onward to its destination; it does not itself release the open resource.
Flushing makes pending text leave the writer's buffer, but the program must still close its file resource.

H

Header row
A header row names the columns in a data file and is handled separately so that its labels are not parsed as ordinary record values.
The header row "name,age" must be skipped or checked before the parser tries to convert an age.

I

IllegalArgumentException
An IllegalArgumentException is an unchecked exception used when a caller supplies a value that violates a method's argument requirements.
A method can throw IllegalArgumentException when its required positive quantity is supplied as -2.
IllegalStateException
An IllegalStateException is an unchecked exception used when an object's current state does not permit the requested operation.
An already-sent order can throw IllegalStateException when code tries to add another item to it.
InputMismatchException
An InputMismatchException is an unchecked scanner failure when a token does not fit the type or range requested by a conversion method.
nextInt() throws InputMismatchException on "several" and leaves that token available to be discarded.

L

Line ending
A line ending is the character sequence terminating a text line, commonly LF on Linux and macOS or CRLF on Windows.
A line ending read by BufferedReader.readLine() is removed before the method returns the line text.
Locale
A locale supplies language and regional formatting conventions that can affect scanner number parsing and formatted decimal output.
Selecting the root locale makes formatted decimal data use "3.50" regardless of a computer's settings.

M

Multi-catch
A multi-catch is one catch clause joining unrelated exception types with a vertical bar so that they share the same handler body.
A multi-catch can report a malformed record for either a bad integer field or a missing array element.

N

NullPointerException
A NullPointerException is an unchecked exception raised when an operation requires an object but receives or uses a null reference.
Calling name.trim() when name is null throws NullPointerException before any trimmed text is returned.
NumberFormatException
A NumberFormatException is an unchecked exception raised when a numeric text conversion cannot produce the requested numeric value.
Integer.parseInt("blue") throws NumberFormatException because the text cannot represent an integer.

P

Parsing
Parsing interprets text according to an expected structure, converting fields into values or objects the program can use.
Parsing a name-and-age record checks its two fields before converting the age and constructing a person.
Path
A Path is an object representing a location in a file system; constructing it does not open, create, or check the named file.
Path.of("data", "counts.txt") constructs a Path without testing whether the data folder exists.
Pending return
A pending return is a return whose expression has been evaluated but whose transfer to the caller waits for required cleanup to finish.
Changing a local integer during finally does not reevaluate the expression of a pending return.
PrintWriter
A PrintWriter writes formatted character output with print-style methods that record I/O failures internally for checkError to report.
A PrintWriter can format an average with printf, but successful return from that call does not prove saving succeeded.
Propagation
Propagation is the passing of an unhandled exception outward through enclosing code and calling methods until a handler is found.
Propagation carries a failed read out of a file-reading helper to a caller that can ask for a different file.
Protected region
A protected region is the work enclosed by a try statement; its boundary determines what is abandoned when a failure reaches its handler.
The protected region covers one record when a conversion try statement is inside the loop body.

R

Record-level failure
A record-level failure makes one input record unusable while allowing later records to be processed under a skip-and-report policy.
A record-level failure reports "Line 6: invalid temperature" and leaves the next iteration reachable.
Recovery
Recovery is the program's response that leaves it able to continue meaningfully after a failure, such as retrying or skipping a bad record.
Recovery in an input loop reads a fresh line before trying another conversion, so it can make progress.
Relative path
A relative path identifies a location from the working directory instead of starting at the file system's root or a drive root.
The relative path data/counts.txt can identify a different file when the program starts in another folder.
Resource
A resource is an object holding an external facility, such as an open file, that must be released after its use ends.
A file reader is a resource that should close even when processing its next line fails.
RuntimeException
RuntimeException is the Exception subclass whose descendants represent unchecked failures, including invalid arguments and null-reference use.
NumberFormatException reaches RuntimeException through its superclass IllegalArgumentException.

S

Scanner
A Scanner reads text as tokens or lines and offers conversion methods, while recording underlying I/O read failures for later inspection.
A file Scanner needs an ioException() check after its loop so a failed read cannot look successful.
Stack trace
A stack trace reports an exception and its active method calls, starting with the detection point and continuing through its callers.
When a helper called by main fails a conversion, the stack trace points first to the conversion, then to the helper and main.
Suppressed exception
A suppressed exception is an additional failure attached to a primary exception, such as a close failure after a resource body has already thrown.
The suppressed exception preserves a reader's closing failure while the original parsing failure propagates.

T

Temporary file
A temporary file holds intermediate output separately from the final destination so it can be completed before a replacement is attempted.
A temporary file for a report is created in the destination folder before the completed text is moved into place.
throw
The throw keyword starts a statement that sends an exception object out of the current operation and interrupts its normal execution.
A throw before field assignment rejects an invalid capacity while preserving the old field value.
Throwable
Throwable is the Java superclass of objects that can be thrown, with Error and Exception as its two main direct subclasses.
A custom checked exception belongs to Throwable through Exception, so Java can throw and catch it.
throws clause
A throws clause is part of a method declaration that lists possible escaping exception types and passes checked handling duties to callers.
The throws clause throws IOException lets a file helper report failure to a caller that can recover.
Truncation
Truncation removes an existing file's contents when it is opened for replacement, before new output has necessarily been written successfully.
Default Files.writeString causes truncation, so a later write failure can leave an incomplete result.
try block
A try block encloses work whose exceptions can be handled by attached catch clauses, with its remaining statements skipped on failure.
A try block that converts text to an integer and then prints it stops before the print statement when conversion fails.
Try-with-resources
Try-with-resources is a Java statement that automatically closes successfully opened AutoCloseable resources when protected work exits.
Try-with-resources closes a writer before the reader when their header declarations open the reader first.

U

Unchecked exception
An unchecked exception belongs to RuntimeException or Error, or a subclass of either, and has no mandatory catch-or-declare requirement.
A wrong array index causes an unchecked exception even when the program has compiled successfully.
UncheckedIOException
An UncheckedIOException is a standard RuntimeException subclass that wraps an IOException while keeping the original file failure as its cause.
An override unable to declare IOException can pass a file failure onward using UncheckedIOException.
Unreachable handler
An unreachable handler is a catch clause that cannot receive an exception because an earlier handler already covers every matching type.
Putting IOException first creates an unreachable handler if NoSuchFileException is caught afterward.
UTF-8
UTF-8 is a Unicode character encoding that uses one byte for basic Latin characters and up to four bytes for other Unicode characters.
In UTF-8, "café" occupies five bytes even though it contains only four visible characters.

W

Whole-file failure
A whole-file failure prevents a file operation from completing reliably, such as a missing input or a disk error while saving a report.
A whole-file failure during reading must stop saving so incomplete input is not reported as a complete result.
Working directory
The working directory is the program's current starting folder for relative paths, which can differ from the source-code folder.
With /work/app as the working directory, data/counts.txt points inside /work/app/data.

About this lesson

By StudeliReport a mistake

Make your own Study Materials

Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.

Get Started