Базовый ввод-вывод

В Java ввод и вывод (I/O — Input/Output) построен на концепции потоков (streams) — упорядоченных последовательностей данных. Поток может быть байтовым (InputStream/OutputStream) или символьным (Reader/Writer).

Класс System предоставляет три стандартных потока, доступных в любом месте программы:

  • ``System.in`` — байтовый поток ввода (по умолчанию — клавиатура).

  • ``System.out`` — поток вывода (PrintStream, обычно консоль).

  • ``System.err`` — поток ошибок (тоже PrintStream, отдельный канал для диагностики).

Для удобного чтения с клавиатуры используется класс java.util.Scanner, который оборачивает InputStream и позволяет считывать примитивы и строки.

Синтаксис

import java.util.Scanner;

Scanner sc = new Scanner(System.in);
String  s = sc.nextLine();      // строка
int     n = sc.nextInt();       // число
double  d = sc.nextDouble();    // дробное

System.out.println("Hello");    // обычный вывод
System.err.println("Error!");   // вывод ошибки

Пример 1. Чтение строки и числа

import java.util.Scanner;

public class ReadInput {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("Имя датчика: ");
        String name = sc.nextLine();
        System.out.print("Пин: ");
        int pin = sc.nextInt();
        System.out.println("Настроен " + name + " на пин " + pin);
        sc.close();
    }
}

Ввод/Output:

Имя датчика: DHT22
Пин: 7
Настроен DHT22 на пин 7

Пример 2. printf для форматированного вывода

public class PrintfDemo {
    public static void main(String[] args) {
        String sensor = "BMP280";
        double temp   = 23.456;
        int    hum    = 47;

        System.out.printf("%-8s t=%.1f°C h=%d%%%n", sensor, temp, hum);
        System.out.printf("%-8s t=%.1f°C h=%d%%%n", "DHT22", 22.1, 53);
    }
}

Output:

BMP280   t=23.5°C h=47%
DHT22    t=22.1°C h=53%

Пример 3. System.err и коды возврата

public class StderrDemo {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.err.println("Ошибка: не передан путь к конфигу");
            System.exit(1);
        }
        System.out.println("Конфиг: " + args[0]);
    }
}

Output (без аргументов):

Ошибка: не передан путь к конфигу

Пример 4. Чтение нескольких значений

import java.util.Scanner;

public class MultiRead {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Введите 3 показания температуры:");
        double sum = 0;
        for (int i = 0; i < 3; i++) {
            sum += sc.nextDouble();
        }
        System.out.printf("Среднее: %.2f%n", sum / 3);
        sc.close();
    }
}

Ввод/Output:

Введите 3 показания температуры:
22.5 23.1 21.8
Среднее: 22.47

Пример 5. Чтение байтов из System.in

import java.io.IOException;

public class RawInput {
    public static void main(String[] args) throws IOException {
        System.out.print("Введите символ и Enter: ");
        int b = System.in.read();
        System.out.println("Код: " + b + " (" + (char) b + ")");
    }
}

Ввод/Output:

Введите символ и Enter: A
Код: 65 (A)

Пример 6. Перенаправление потоков

import java.io.PrintStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class RedirectStdout {
    public static void main(String[] args) throws IOException {
        PrintStream original = System.out;
        try (PrintStream file = new PrintStream(new FileOutputStream("app.log"))) {
            System.setOut(file);
            System.out.println("Эта строка попадёт в app.log");
        } finally {
            System.setOut(original);
        }
        System.out.println("А эта — снова в консоль");
    }
}

Output:

А эта — снова в консоль

Подводные камни

Предупреждение

  • ``Scanner.nextInt()`` не съедает перевод строки — последующий nextLine() вернёт пустую строку.

  • Закрытие ``Scanner(System.in)`` также закрывает System.in, переоткрыть его в той же JVM не получится.

  • ``System.err`` не буферизуется и выводится сразу — удобно для отладки.

  • ``System.exit(0)`` пропускает блоки ``finally`` — будьте осторожны при работе с ресурсами.

  • ``System.out.println`` дорог по производительности в горячих циклах из-за синхронизации.

См. также

Примечание

Материал подготовлен на основе официальной документации Oracle Java Tutorials — Lesson: Basic I/O (Oracle Free Documentation License). Текст переведён и переработан, примеры кода написаны заново.