У мові програмування Java введення/виведення інформації побудовано на понятті потоку.
Потік — це абстрактне поняття для позначення джерела чи приймача даних, що може передавати або отримувати дані.
Для використання класу потоку введення/виведення потрібно імпортувати пакет java.io:
import java.io.*;
У мові Java розрізняють два види потоків:
Байтові потоки введення/виведення поділяють на нащадків таких класів:
InputStream — абстрактний клас, що описує байтовий потік введення.
Нащадки InputStreamОсновні методи класу InputStream:
Основні методи класу OutputStream:
Символьні потоки введення/виведення поділяють на нащадків таких класів:
Reader — абстрактний клас, що описує потік введення символів.
Нащадки Reader:Основні методи класу Reader:
Основні методи класу Writer:
f.append(c) — додає в кінець вихідного потоку символ c (тип char), повертає об'єкт Writer;
Стандартні потоки введення/виведення втілені у пакунку java.lang. Цей пакунок імпортується автоматично, тобто не обов’язково використовувати вказівку import. Базовим класом цього пакунку є клас System з трьома змінними, які є посиланнями на стандартні (наперед визначені) потоки введення/виведення:
— див. приклад коду:
package work; import java.io.*; import java.util.Scanner; public class Work { public static void main(String[] args) throws IOException { Scanner s = new Scanner(System.in); InputStream i = System.in; PrintStream o = System.out; PrintStream e = System.err; o.println("Введіть літеру латиниці, цифру або знак пунктуації"); int code = i.read(); o.println("Код введеного символа "+code); o.println("Введіть ціле число "); int n = s.nextInt(); o.println("Було введено число "+n); e.println("Жодних проблем!"); char a[] = new char[5]; InputStreamReader isr = new InputStreamReader(System.in); o.println("Введіть символи (до 5):"); n = isr.read(a, 1, 4); o.println("Кількість введених символів разом з ознакою кінця рядка: " + n); for (int j=0; j<a.length; j++) o.println("a[" + j + "] = " + a[j]); } }
з таким результатом виконання у консолі:
Введіть літеру латиниці, цифру або знак пункткації * Код введеного символа 42 Введіть ціле число 22 Було введено число 22 Жодних проблем! Введіть символи (до 5): qw Кількість введених символів: 3 a[0] = a[1] = q a[2] = w a[3] = a[4] =
Клас Scanner використовують для аналізу і введення даних потоку введення.
Наприклад, для введення цілого числа (не символа, не рядка), як це зроблено у поданому вище прикладі коду.
Методи класу Scanner
Тип результату повертання | Назва методу і тип аргумента (в дужках) | Призначення (що робить?) |
---|---|---|
void | close() | Закриває об'єкт сканера |
Pattern | delimiter() | Повертає шаблон, який об'єкт Scanner в даний час використовує для порівняння роздільників. |
String | findInLine (Pattern) | Повертає об'єкт String, який задовольняє вказаному шаблону. |
String | findInLine (String) | Шукає наступне входження шаблону, створеного з указаного рядка, при незтуванні роздільників. |
String | findWithinHorizon (Pattern, int) | Шукає наступне входження вказаного шаблону. |
String | findWithinHorizon (String, int) | Шукає наступне входження шаблону введення, ігноруючи роздільник |
boolean | hasNext() | Повертає true, якщо у цього сканера є дані на вході, інакше повертає false. |
boolean | hasNext(Pattern) | Повертає true, якщо наступні повні дані відповідають вказаному шаблону, інакше повертає false. |
boolean | hasNext(String) | Повертає true, якщо наступні дані відповідають шаблону, створеному з вказаного рядка, інакше повертає false. |
boolean | hasNextBigDecimal() | Повертає true, якщо наступні дані можна тлумачити як BigDecimal за допомогою методу nextBigDecimal, інакше повертає false. |
boolean | hasNextBigInteger() | Повертає true, якщо наступні дані можна тлумачити як BigInteger за допомогою методу nextBigInteger, інакше повертає false. |
boolean | hasNextBigInteger(int) | Аналог попереднього методу для вказаної основи. |
boolean | hasNextBoolean() | Повертає true, якщо наступні дані потоку мають логічний тип, інакше повертає false. |
boolean | hasNextByte() | Повертає значення true, якщо наступний байт можна перетворити у тип даних байта, інакше повертає false. |
boolean | hasNextByte(int) | Аналог попереднього методу для вказаної основи. |
boolean | hasNextDouble() | Повертає значення true, якщо наступні дані на вході можна тлумачити як значення типу Double за допомогою методу nextDouble, інакше повертає false. |
boolean | hasNextFloat() | Повертає значення true, якщо наступні дані на вході можна тлумачити як значення типу float за допомогою методу nextFloat, інакше повертає false. |
boolean | hasNextInt() | Повертає значення true, якщо наступні дані на вході можна тлумачити як значення типу int за допомогою методу nextInt, інакше повертає false. |
boolean | hasNextInt(int) | Аналог попереднього методу при вказаній основі числення. |
boolean | hasNextLine() | Повертає логічний тип даних, який відповідає новому рядку String, яку містить об'єкт Scanner. |
boolean | hasNextLong() | Повертає true, якщо наступні дані на вході сканера можна тлумачити як значення типу long з використанням методу nextLong, інакше повертає false. |
boolean | hasNextLong(int) | Аналог попереднього методу при вказаній основі числення. |
boolean | hasNextShort() | Повертає true, якщо наступні дані на вході сканера можна тлумачити як значення типу Short з використанням методу nextShort, інакше повертає false. |
boolean | hasNextShort(int) | Аналог попереднього методу при вказаній основі числення. |
IOException | ioException() | Повертає IOException, останній раз виданий в основі сканера Readable. |
Locale | locale() | Повертає локаль. |
MatchResult | match() | Повертає результат останньої дії з об'єктом. |
String | next() | Сканує і повертає наступну повну частину даних. |
String | next (Pattern) | Сканує і повертає наступну повну частину даних, якщо вона відповідає вказаному шаблону. |
String | next (String) | Сканує і повертає наступну повну частину даних, якщо вона відповідає вказаному шаблону, створеному із зазначеного рядка. |
BigDecimal | nextBigDecimal() | Сканує і повертає наступну повну частину даних як BigDecimal. |
BigInteger | nextBigInteger() | Сканує і повертає наступну повну частину даних як BigInteger. |
BigInteger | nextBigInteger(int) | Аналог попереднього методу при вказаній основі числення. |
boolean | nextBoolean() | Сканує і повертає наступну частину даних як логічне значення. |
byte | nextByte() | Сканує і повертає наступну частину даних як тип byte. |
byte | nextByte(int) | Аналог попереднього методу при вказаній основі числення. |
double | nextDouble() | Сканує і повертає наступну частину даних як тип double. |
float | nextFloat() | Сканує і повертає наступну частину даних як тип float. |
int | nextInt() | Сканує і повертає наступну частину даних як тип int. |
int | nextInt(int) | Аналог попереднього методу при вказаній основі числення. |
String | nextLine() | Переміщує сканер за поточний рядок і повертає пройдені дані. |
long | nextLong() | Сканує і повертає наступну частину даних як тип long. |
long | nextLong(int) | Аналог попереднього методу при вказаній основі числення. |
short | nextShort() | Сканує і повертає наступну частину даних як тип short. |
short | nextShort(int) | Аналог попереднього методу при вказаній основі числення. |
int | radix() | Повертає поточну основу числення. |
void | remove() | Вилучає поточний об'єкт. |
Scanner | reset () | Скидає налаштування локалі, радіуса і роздільника. |
Scanner | skip (Pattern) | Пропускає введення, що відповідає вказаному шаблону, нехтуючи роздільниками. |
Scanner | skip (String) | Пропускає введення, що відповідає шаблону, створеному із зазначеного рядка. |
String | toString() | Повертає рядкове подання. |
Scanner | useDelimiter (Pattern) | Встановлює шаблон обмеження поточного сканера за вказаним шаблоном. |
Scanner | useDelimiter (String) | Аналог попереднього методу, але за шаблоном, створеним ызз зазначеного рядка. |
Scanner | useLocale (Locale) | Встановлює вказану локалізацію. |
Scanner | useRadix (int) | Встановлює вказану основу системи числення (radix). |
Зчитування символів з консолі з буферизацією здійснюють, розташувавши представника класу InputStreamReader в оболонку об’єкту класу BufferedReader. Загальна форма конструктора класу BufferedReader така:
BufferedReader(i);
Тут i — потік даних (файл, консоль тощо), тип Reader. У випадку консолі задають представника класу InputStreamReader. Такий підхід реалізує паттерн Декоратор (Decorator). У паттерні Декоратор екземпляр одного класу служить оболонкою для екземпляру іншого класу. Таким чином відбувається нашаровування об’єктів — див. приклад зчитування символів з консолі з буферизацією.
package work; import java.io.*; public class Work { public static void main(String[] args) throws IOException { PrintStream o = System.out; InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); char c; o.println("Введіть символи, '/' - для виходу."); do { c = (char) br.read(); o.println(c); } while (c != '/'); } }
з таким можливим виглядом консолі.
Введіть символи, '/' - для виходу. qw q w e/ e /
Введення з консолі й розбиття рядків проілюструємо таким прикладом:
package work; import java.io.*; import java.util.Scanner; public class Work { public static void main(String[] args) throws IOException { Scanner in = new Scanner(System.in); System.out.print("Введіть рядок тексту: слова, розділені пробілом.\n"); String s = in.nextLine(); String[] t = s.split(" "); // розбиття за роздільником " " - пробілом System.out.println("Введений рядок містить "+t.length+" слів."); for (int j=0; j<t.length; j++) {System.out.println(t[j]);} } }Метод split класу String має два аргументи:
обов'язковий — рядок регулярного виразу, за яким здійснюють розбиття. Якщо використовують кілька роздільників, їх записують через вертикальну риску |.
необов'язковий — кількість слів (тип int), рахуючи від початку рядка. Якщо не вказано або вказано від'ємне значення, буде виділено всі всі слова.
Клас File містить кілька конструкторів файлових об'єктів, кожен з яких дозволяє формувати назву файлу (у тому числі теки) різними способами. Найуживанішим є конструктор, що отримує один рядок типу String, уякому записано повну (абсолютну) або скорочену (відносну) назву файлу, який пов'язують з файловим об'єктом. Також є конструктори, що формують назву файлу з кількох частин — див. приклад з використанням методу getPath, описаного нижче.
package work; import java.io.File; public class Work { public static void main(String[] args) { File f1 = new File("output.txt"); System.out.println(f1.getPath()); File f2 = new File("/home", "/chief"); System.out.println(f2.getPath()); File f3 = new File(f2,"output.txt"); System.out.println(f3.getPath()); } }
Результат виконання програми такий:
output.txt /home/chief /home/chief/output.txt
Основні методи класу File
f.getName() — повертає рядок — назву файлу файлового об'єкта f;
f.getPath() — повертає рядок — адресу файлового об'єкта f, задану при його створенні (назва з розширенням або повний шлях);
f.isAbsolute() — повертає truе або false — результат визначення, чи було вказано повний шлях до файлу при створенні файлового об'єкта f;
f.getAbsolutePath() — повертає рядок — повний шлях до файлу, пов'заного з файловим об'єктом f;
f.canRead() — повертає truе або false — результат визначення того, чи допускає файловий об’єкт f читання;
f.canWrite() — повертає truе або false — результат визначення того, чи допускає файловий об’єкт f запис;
f.exists() — повертає truе або false — результат визначення наявності файлу (каталогу);
f.isDirectory() — повертає truе або false — результат визначення того, чи зв’язаний файловий об’єкт а є текою (директорією, каталогом);
f.isFile() — повертає truе або false — результат визначення того, чи зв’язаний файловий об’єкт f є файлом, що не є текою;
f.isHidden() — повертає truе або false — результат визначення того, чи файловий об’єкт f є прихованим;
f.length() — повертає ціле число типу long — розмір у байтах файлу, зв’язаного з файловим об’єктом f;
f.delete() — видаляє файл, зв’язаний з файловим об’єктом f. Повертає truе при успішному видаленні, інакше повертає false;
f.mkdir() — створює теку (директорію, каталог), зв’язану з файловим об’єктом f. Повертає truе при успішному створенні, інакше повертає false;
f.mkdirs() — створює послідовність вкладених тек (директорій, каталогів), якщо при створенні файлового об’єкту f в аргументі конструктора File записано послідовність вкладених тек, розділених
подвійними зворотніми похилими рисками (подвійними — з метою екранування службового символу). Як, наприклад, у такій вказівці:
File f = new File("C:\\a\\b\\c");
Повертає truе при успішному створенні, інакше повертає false;
f.renameTo(g) — змінює назву файлу, зв’язаного з файловим об’єктом f, на ту, що зв'язана з файловим об’єктом g. Повертає truе при успішній зміні назві, інакше повертає false;
f.getTotalSpace() — повертає ціле число типу long — розмір у байтах диску, зв'язаного з файловою змінною f;
f.getFreeSpace() — повертає ціле число типу long — розмір у байтах вільного місця на диску, зв'язаного з файловою змінною f. Якщо при конструюванні файлової змінної вказано не лиск, а назву файлу, то визначають об’єм вільного місця для носія, на якому цей файл розташовано;
f.getUsableSpace() — повертає ціле число типу long — розмір у байтах корисного вільного місця на диску, зв'язаного з файловою змінною f. Якщо при конструюванні файлової змінної вказано не диск, а назву файлу, то визначають об’єм вільного місця для носія, на якому цей файл розташовано.
Клас FileOutputStream призначено для запису байтів у файл. Він є похідним від класу OutputStream, тому успадковує всю його функціональність. Конструктор FileOutputStream має один два аргументи:
Якщо вказаного файлу немає, то його буде автоматично створено. Для записку рядка його потрібно спочатку перетворити у масив байтів — див. приклад запису рядка у файл.
package work; import java.io. *; public class Work { public static void main (String [] args) { String s = "Текст для запису"; // рядок для запису try (FileOutputStream fout = new FileOutputStream ("output.txt")) { byte [] b = s.getBytes(); // перетворення рядка у масив байтів fout.write (b, 0, b.length); } catch (IOException ex) {System.out.println(ex.getMessage());} System.out.println ("Файл успішно записано"); } }
Для автоматичного закриття файлу і звільнення ресурсу об'єкт FileOutputStream створюють за допомогою вказівки вигляду try … catch. При потребі записати лише один (перший) байт використовують перевантаження методу write:
fout.write(b[0]);
Клас FileInputStream призначено для зчитування даних з файлу. Він є спадкоємцем класу InputStream і реалізує всі його методи. Для створення об'єкта FileInputStream використовують декілька конструкторів. Найчастіше використовуваний як параметр використовує рядок s — шлях до зчитувати файлу:
FileInputStream (s) throws FileNotFoundException
Якщо файл не можливо відкрити (наприклад, за вказаним шляхом такого файлу немає), то буде породжено виключення FileNotFoundException.
Розглянемо приклад виведення у консоль даних з раніше створеного файлу.
package work; import java.io. *; public class Work { public static void main (String [] args) { try (FileInputStream fin = new FileInputStream ("input.txt")) { System.out.printf ( "Розмір файлу: %d байт \n",fin.available()); int i = -1; while ( (i = fin.read()) != -1) {System.out.print ((char) i);} } catch (IOException ex) {System.out.println (ex.getMessage());} } }
У розглянутому прикладі байти зчитють у змінну i доти, поки поток непорожній, тобто поки метод read число, відмінне від -1. Потім кожний зчитаний байт перетворюють в об'єкт типу char і виводять у консоль. Якщо текст містить літери кирилиці, можливе неправильне відображення вмісту файлу в консолі.
Перевірку умови fin.read()) != -1 можна замінити на перевірку справдження виразу fin.ready().
Переписати вміст одного файлу в інший можна таким чином.
package work; import java.io. *; public class Work { public static void main (String [] args) { try (FileInputStream fin = new FileInputStream ("input.txt"); FileOutputStream fout = new FileOutputStream("output.txt") ) { byte [] b = new byte [fin.available()]; fin.read (b, 0, b.length); fout.write(b, 0, b.length); } catch (IOException ex) {System.out.println(ex.getMessage());} } }
Клас FileWriter. Зазвичай використовують конструктор класу з такими двома аргументами:
Є що конструктор з одним аргументом типу FileDescriptor.
Якщо вказаного файлу немає, то його буде створено автоматично.
Наступний приклад ілюструє переписування вмісту файлу input.txt у файл output.txt
package work; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class Work { public static void main(String[] args) { try { FileReader in = new FileReader( "input.txt"); FileWriter out= new FileWriter("output.txt"); BufferedReader bin = new BufferedReader(in); String s = bin.readLine(); while (s != null) { out.write(s+"\n"); System.out.println(s); s = bin.readLine(); } out.close(); } catch (FileNotFoundException e) {} catch (IOException e) {} } }
Текст упорядкував Олександр Рудик.