PrintStream это класс из пакета
java.io, который печатает данные в поток вывода. Именно его объектом является
System.out, поэтому привычный
System.out.println() это вызов метода
PrintStream. Тот же класс умеет писать не в консоль, а в файл: путь или объект
File передают прямо в конструктор. Кроме
print() и
println() у него есть
printf() для форматированного вывода.
Кратко
System.out это объект PrintStream, поэтому System.out.println() это метод именно данного класса.- В конструктор можно передать
OutputStream, объект File или строку с путем к файлу, и тогда вывод пойдет в файл, а не в консоль. printf() печатает форматированную строку: %s подставит строку, %d целое число, %b значение boolean.- Шаблон для
printf() удобно вынести в константу и менять только подставляемые значения. System.in это InputStream, по умолчанию привязанный к клавиатуре.- Источник ввода можно подменить: обернуть данные в
ByteArrayInputStream и передать в System.setIn(). Присвоить System.in напрямую нельзя, поле объявлено final.
Привет!
Сегодня поговорим о классе
PrintStream и всем, что он умеет делать.
![Печатный станок в работе: класс PrintStream отвечает за печать данных в поток]()
Собственно, с двумя методами класса
PrintStream ты уже знаком. Это методы
print() и
println(), которыми ты пользуешься, наверное, каждый день :)
Поскольку переменная
System.out является объектом
PrintStream, вызывая метод
System.out.println(), ты вызываешь метод именно этого класса.
Общее назначение класса PrintStream это вывод информации в какой-то поток.Конструкторы PrintStream: вывод в файл
У данного класса есть несколько конструкторов. Вот несколько наиболее распространенных:
PrintStream(OutputStream outputStream)
PrintStream(File outputFile) throws FileNotFoundException
PrintStream(String outputFileName) throws FileNotFoundException
Как видишь, мы можем передать в конструктор объекта
PrintStream, например, название файла, в который необходимо вывести данные.
Или же, как альтернативу, сам объект
File.
Начиная с Java 10 у тех же конструкторов есть варианты с явным указанием кодировки, например
PrintStream(String fileName, Charset charset). Держи их в уме, если пишешь в файл не только латиницу: до Java 18 кодировкой по умолчанию была системная, а не UTF-8.
Давай рассмотрим, как это работает на примерах:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
public class Main {
public static void main(String arr[]) throws FileNotFoundException
{
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
filePrintStream.println(222);
filePrintStream.println("Hello world");
filePrintStream.println(false);
}
}
Этот код создаст на рабочем столе файл
test.txt (если он там еще не существует) и запишет туда последовательно наши число, строку и
boolean-переменную.
Вот содержимое нашего файла после работы программы:
222
Hello world
false
Как мы и сказали выше, не обязательно передавать сам объект файла
File. Достаточно просто указать в конструкторе путь к нему:
import java.io.FileNotFoundException;
import java.io.PrintStream;
public class Main {
public static void main(String arr[]) throws FileNotFoundException
{
PrintStream filePrintStream = new PrintStream("C:\\Users\\Username\\Desktop\\test.txt");
filePrintStream.println(222);
filePrintStream.println("Hello world");
filePrintStream.println(false);
}
}
Этот код сделает то же, что и предыдущий.
Метод printf(): форматированный вывод
Еще один интересный метод, на который стоит обратить внимание, это
printf(), или вывод форматированной строки. Что значит «форматированная строка»?
Чтобы объяснить, приведу пример:
import java.io.IOException;
import java.io.PrintStream;
public class Main {
public static void main(String[] args) throws IOException {
PrintStream printStream = new PrintStream("C:\\Users\\Евгений\\Desktop\\test.txt");
printStream.println("Hello!");
printStream.println("I'm robot!");
printStream.printf("My name is %s, my age is %d!", "Amigo", 18);
printStream.close();
}
}
Здесь вместо того, чтобы явно записывать в строке имя и возраст нашего робота, мы как бы оставляем для этой информации «свободное место» с помощью указателей
%s и
%d.
А те данные, которые должны оказаться в этих местах, мы передаем в качестве параметров. В нашем случае это строка «
Amigo» и число 18. Мы могли бы, например, создать еще одно пространство: скажем,
%b, и передать еще один параметр.
Для чего это нужно?
Прежде всего, для повышения гибкости.
Если в твоей программе необходимо будет часто выводить приветственное сообщение, для каждого нового робота тебе придется вручную набирать нужный текст. Ты не сможешь даже вынести этот текст в константу: имена и возраст-то у всех разные!
Но используя новый метод, ты можешь вынести строку с приветствием в константу, а при необходимости просто менять параметры в методе
printf().
import java.io.IOException;
import java.io.PrintStream;
public class Main {
private static final String GREETINGS_MESSAGE = "My name is %s, my age is %d!";
public static void main(String[] args) throws IOException {
PrintStream printStream = new PrintStream("C:\\Users\\Евгений\\Desktop\\test.txt");
printStream.println("Hello!");
printStream.println("We are robots!");
printStream.printf(GREETINGS_MESSAGE, "Amigo", 18);
printStream.printf(GREETINGS_MESSAGE, "R2-D2", 35);
printStream.printf(GREETINGS_MESSAGE, "C-3PO", 35);
printStream.close();
}
}
Подмена System.in
В этой лекции мы будем «бороться с системой» и научимся подменять переменную
System.in и перенаправлять системный ввод в нужное нам место.
![Деревянный указатель-стрелка на фоне заснеженных гор: System.in можно перенаправить на другой источник данных]()
Ты мог подзабыть, что такое
System.in, но эту конструкцию ни один студент JavaRush не забудет никогда:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.in (как и
System.out) это статическая переменная класса
System. Но, в отличие от
System.out, она относится к другому классу, а именно к
InputStream.
По умолчанию
System.in это поток, считывающий данные с системного устройства, с клавиатуры. Однако, как и в случае с
System.out, мы можем подменить источник данных, и чтение будет происходить не с клавиатуры, а из нужного нам места!
Давай рассмотрим пример:
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
String greetings = "Привет! Меня зовут Амиго!\nЯ изучаю Java на сайте JavaRush.\nОднажды я стану крутым программистом!\n";
byte[] bytes = greetings.getBytes();
InputStream inputStream = new ByteArrayInputStream(bytes);
System.setIn(inputStream);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String str;
while ((str = reader.readLine())!= null) {
System.out.println(str);
}
}
}
Итак, что же мы сделали?
Обычно
System.in «привязана» к клавиатуре. Но мы не хотим, чтобы данные читались с клавиатуры: пусть читаются из обычной строки с текстом!
Мы создали строку, и получили ее в виде массива байт. Зачем нам байты? Дело в том, что
InputStream это
абстрактный класс, и мы не можем создать его экземпляр. Придется выбрать какой-то класс из числа его наследников. Для примера можем взять
ByteArrayInputStream. Он простой, и по одному названию понятно, как он работает: источником данных для него является массив байт.
Так что мы создаем этот самый массив байт и передаем в конструктор нашему
stream’у, который будет читать данные.
По сути, все уже готово! Теперь нам достаточно использовать метод
System.setIn(), чтобы явно установить значение переменной
in. В случае с
out, как ты помнишь, установить значение переменной явно тоже было нельзя: приходилось использовать специальный метод
setOut().
После того, как мы присвоили созданный нами
InputStream переменной
System.in, надо проверить, сработала ли наша задумка.
В этом нам поможет старый знакомый
BufferedReader.
В обычной ситуации этот код привел бы к тому, что у тебя в IntelliJ IDEA открылась бы консоль, и оттуда считывались данные, которые ты вводил с клавиатуры.
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String str;
while ((str = reader.readLine())!= null) {
System.out.println(str);
}
Но, запустив его теперь, ты увидишь, что в консоль просто выведется наш текст из программы, никакого считывания с клавиатуры не будет. Мы подменили источник данных, теперь им является не клавиатура, а наша строка!
Вот так легко и просто :)
В сегодняшней лекции мы познакомились с новым классом и рассмотрели новый небольшой «хак» по работе с вводом-выводом. Самое время вернуться к курсу и решить несколько задач :)
Увидимся на следующей лекции!
Вопросы и ответы
Почему System.out.println() это метод класса PrintStream?
System.out это статическая переменная класса System, и ее тип как раз PrintStream. Вызывая System.out.println(), ты вызываешь метод объекта PrintStream, который привязан к консоли.
Как вывести данные в файл с помощью PrintStream?
Передать в конструктор объект File или строку с путем к файлу. После этого println() и printf() пишут не в консоль, а в этот файл. Если файла еще нет, он будет создан.
Что означают %s и %d в printf()?
Это места для подстановки значений: %s подставит строку, %d целое число, %b значение boolean. Сами значения передают следующими аргументами метода, в том же порядке, в каком идут указатели.
Нужно ли закрывать PrintStream?
Поток, открытый на файл, закрывать нужно, иначе останется занятый дескриптор. Для этого вызывают close() или, что удобнее, создают поток в конструкции try-with-resources. Поток System.out закрывать не надо.
Зачем подменять System.in?
Чтобы программа читала данные не с клавиатуры, а из заранее подготовленного источника. Это удобно для тестов и автопроверки: не нужно каждый раз вручную вводить строки в консоль.
Чем System.in отличается от System.out?
Обе переменные статические и принадлежат классу System, но System.out это PrintStream для вывода, а System.in это InputStream для ввода. Присвоить им значение напрямую нельзя, поля объявлены final, поэтому используют методы setOut() и setIn().
Источник:
Oracle: класс PrintStream.
Читайте также