Перейти к основному содержимому

BufferedReader против консоли против сканера в Java

· 4 мин. чтения

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 .
  • Рассмотрим консоль , если мы читаем защищенные данные с системной консоли и хотим скрыть то, что вводится
  • Используйте Scanner , если нам нужно проанализировать входной поток с помощью пользовательского регулярного выражения.
  • Сканер был бы предпочтительнее, когда мы взаимодействуем с системной консолью, поскольку он предлагает точные методы для чтения и анализа входного потока. Кроме того, недостаток производительности не является большой проблемой, так как в большинстве случаев методы nextXXX блокируются и ждут ручного ввода .
  • В потокобезопасном контексте рассмотрите BufferedReader , если только нам не нужно использовать функции, специфичные для класса Console .