«1. Обзор

В этой статье мы рассмотрим различия между классами BufferedReader, Console и Scanner в Java.

Чтобы глубже погрузиться в каждую тему, мы предлагаем ознакомиться с нашими отдельными статьями о сканере Java, консольном вводе-выводе в Java и BufferedReader.

2. Пользовательский ввод

Учитывая базовый поток, передаваемый конструкторам, классы BufferedReader и Scanner могут обрабатывать более широкий диапазон пользовательского ввода, например строку, файл, системную консоль (которая обычно подключается к клавиатура) и розетка.

С другой стороны, класс Console предназначен для доступа только к символьной системной консоли, если таковая имеется, связанной с текущей виртуальной машиной Java.

Давайте посмотрим на конструкторы BufferedReader, которые принимают разные входные данные:

BufferedReader br = new BufferedReader(
  new StringReader("Bufferedreader vs Console vs Scanner in Java"));
BufferedReader br = new BufferedReader(
  new FileReader("file.txt"));
BufferedReader br = new BufferedReader(
  new InputStreamReader(System.in))

Socket socket = new Socket(hostName, portNumber);
BufferedReader br =  new BufferedReader(
  new InputStreamReader(socket.getInputStream()));

Класс Scanner также может принимать разные входные данные в своих конструкторах:

Scanner sc = new Scanner("Bufferedreader vs Console vs Scanner in Java")
Scanner sc = new Scanner(new File("file.txt"));
Scanner sc = new Scanner(System.in);

Socket socket = new Socket(hostName, portNumber);
Scanner sc =  new Scanner(socket.getInputStream());

Класс Console доступен только через вызов метода:

Console console = System.console();

Имейте в виду, что когда мы используем класс Console, системная консоль, связанная с JVM, недоступна, если мы запускаем код в среде IDE, такой как Eclipse или IntelliJ IDEA.

3. Пользовательский вывод

В отличие от классов BufferedReader и Scanner, которые ничего не записывают в поток вывода, класс Console предлагает несколько удобных методов, таких как readPassword (String fmt, Object… args), readLine ( String fmt, Object… args) и printf (String format, Object… args), чтобы записать приглашение в поток вывода системной консоли:

String firstName = console.readLine("Enter your first name please: ");
console.printf("Welcome " + firstName );

Итак, когда мы пишем программу для взаимодействия с системной консолью , класс Console упростит код, удалив ненужный System.out.println.

4. Анализ входных данных

Класс Scanner может анализировать примитивные типы и строки, используя регулярные выражения.

Он разбивает входные данные на токены, используя специальный шаблон разделителя, который по умолчанию соответствует пробелу:

String input = "Bufferedreader vs Console vs Scanner";
Scanner sc = new Scanner(input).useDelimiter("\\s*vs\\s*");
System.out.println(sc.next());
System.out.println(sc.next());
System.out.println(sc.next());
sc.close();

Классы BufferredReader и Console просто читают входной поток как есть.

5. Чтение защищенных данных

Класс Console имеет методы readPassword() и readPassword (String fmt, Object… args) для чтения защищенных данных с отключенным эхом, чтобы пользователи не видели, что они печатают: ~~ ~

String password = String.valueOf(console.readPassword("Password :"));

BufferedReader и Scanner не имеют такой возможности.

6. Потокобезопасность

Все методы чтения в BufferedReader и методы чтения и записи в Console синхронизированы, а методы в классе Scanner — нет. Если мы читаем пользовательский ввод в многопоточной программе, лучшим вариантом будет либо BufferedReader, либо Console.

7. Размер буфера

Размер буфера составляет 8 КБ в BufferedReader по сравнению с 1 КБ в классе Scanner.

Кроме того, при необходимости мы можем указать размер буфера в конструкторе класса BufferedReader. Это поможет при чтении длинных строк из пользовательского ввода. Консольный класс не имеет буфера при чтении из системной консоли, но имеет буферизованный поток вывода для записи в системную консоль.

8. Разное

Существуют некоторые различия, которые не являются основными факторами, которые мы учитываем при выборе подходящего класса для использования в различных ситуациях.

8.1. Закрытие потока ввода

Создав экземпляр BufferedReader или Scanner, нужно не забыть закрыть его, чтобы избежать утечки памяти. Но этого не происходит с классом Console — нам не нужно закрывать системную консоль после использования.

8.2. Обработка исключений

В то время как Scanner и Console используют подход с непроверяемыми исключениями, методы в BufferedReader генерируют проверенные исключения, что вынуждает нас писать шаблонный синтаксис try-catch для обработки исключений.

9. Заключение

Теперь, когда мы определили различия между этими классами, давайте придумаем несколько эмпирических правил относительно того, какие из них лучше всего подходят для решения различных ситуаций:

    «Используйте BufferedReader, если нам нужно прочитать длинные строки из файла, так как он имеет лучшую производительность, чем Scanner. Используйте Console, если мы читаем защищенные данные с системной консоли и хотим скрыть то, что вводится. Используйте Scanner, если нам нужно проанализировать ввод. stream с пользовательским регулярным выражением Scanner будет предпочтительнее, когда мы взаимодействуем с системной консолью, поскольку он предлагает точные методы для чтения и анализа входного потока. Кроме того, недостаток производительности не является большой проблемой, так как в большинстве случаев методы nextXXX блокируются и ждут ручного ввода. В контексте потокобезопасности рассмотрите BufferedReader, если только нам не нужно использовать функции, специфичные для класса Console