IOException în Java

Excepția verificată pentru erori de intrare/ieșire (fișier lipsă, fără drepturi, disc plin); trebuie prinsă sau declarată.

Sintaxă
import java.io.IOException;

public class IOException extends Exception
// subclase: FileNotFoundException, NoSuchFileException, FileAlreadyExistsException,
//           AccessDeniedException, DirectoryNotEmptyException ...

Ce face IOException

IOException semnalează că o operație cu fișiere, rețea sau alte fluxuri a eșuat. Este o excepție verificată (checked): compilatorul te obligă fie să o prinzi cu try/catch, fie să scrii throws IOException în semnătura metodei.

Are multe subclase mai precise: NoSuchFileException și FileNotFoundException (fișier lipsă), FileAlreadyExistsException, AccessDeniedException, DirectoryNotEmptyException. Pune blocurile catch de la cea mai precisă la cea mai generală.

În lambda-uri (de exemplu în forEach sau map) nu poți arunca o excepție verificată. Acolo o învelești în UncheckedIOException, care nu trebuie declarată.

Ce returnează

Este o clasă de excepție; getMessage() dă de obicei calea fișierului sau descrierea erorii.

Exemple

Exemplul 1: Prinderea erorilor de la cea mai precisă la cea generală

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

public class Main {
    static void afiseaza(String nume) {
        try {
            System.out.println(nume + ": " + Files.readString(Path.of(nume)).strip());
        } catch (NoSuchFileException e) {
            System.out.println(nume + ": fișierul nu există");
        } catch (IOException e) {
            System.out.println(nume + ": eroare " + e.getClass().getSimpleName());
        }
    }

    public static void main(String[] args) throws IOException {
        Files.writeString(Path.of("bun.txt"), "Totul e în regulă.");
        Files.createDirectory(Path.of("folder"));

        afiseaza("bun.txt");
        afiseaza("lipsa.txt");
        afiseaza("folder");
    }
}

Rezultat

bun.txt: Totul e în regulă.
lipsa.txt: fișierul nu există
folder: eroare IOException

Exemplul 2: throws și UncheckedIOException într-o lambda

Metoda citeste declară throws IOException. În lambda din map nu putem face asta, așa că o învelim în UncheckedIOException.

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

public class Main {
    static String citeste(Path p) throws IOException {
        return Files.readString(p).strip();
    }

    public static void main(String[] args) throws IOException {
        Files.writeString(Path.of("a.txt"), "Ana");
        Files.writeString(Path.of("b.txt"), "Radu");

        List<String> continut = List.of(Path.of("a.txt"), Path.of("b.txt")).stream()
                .map(p -> {
                    try {
                        return citeste(p);
                    } catch (IOException e) {
                        throw new UncheckedIOException(e);
                    }
                })
                .toList();
        System.out.println(continut);

        try {
            List.of(Path.of("c.txt")).forEach(p -> {
                try {
                    citeste(p);
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            });
        } catch (UncheckedIOException e) {
            System.out.println("Eroare: " + e.getCause().getClass().getSimpleName() + " " + e.getCause().getMessage());
        }
    }
}

Rezultat

[Ana, Radu]
Eroare: NoSuchFileException c.txt

Greșeli frecvente

  • Prinzi excepția și nu faci nimic (catch (IOException e) {}). Eroarea dispare fără urmă; cel puțin afișeaz-o sau aruncă alta mai sus.
  • Pui catch (IOException e) înaintea lui catch (NoSuchFileException e): codul nu compilează, pentru că al doilea bloc nu mai poate fi atins.
  • Uiți că și close() poate arunca IOException. Cu try-with-resources această eroare este tratată automat.

Comenzi înrudite

  • Files: Clasa cu metode statice pentru lucrul cu fișiere și foldere: citire, scriere, copiere, mutare, ștergere, listare.
  • Files.readString: Citește tot conținutul unui fișier text într-un singur String (implicit în UTF-8).
  • InputStream: Clasa de bază pentru citirea de octeți (fișiere, rețea, System.in); readAllBytes citește tot conținutul într-un byte[].
  • BufferedReader: Citește text eficient, rând cu rând, dintr-un fișier, de la tastatură sau din alt Reader; close închide sursa.