"Здравей, Амиго! Днес ще се запознаем с входно/изходните потоци . Подбрахме тази тема преди няколко дни, но днес ще я проучим обстойно. Входно/изходните потоци са разделени на 4 категории:"

1) Потоците се разделят според тяхната посока: входни потоци и изходящи потоци

2) Потоците се разделят според техния тип данни: такива, които работят с byteове и такива, които работят със знаци .

Тук тези разделения са представени в table:

Входящ поток Изходен поток
Работи с byteове InputStream OutputStream
Работи с герои Читател Писател

Ако даден обект имплементира интерфейса InputStream , тогава той поддържа възможността за последователно четене на byteове от него.

Ако даден обект имплементира интерфейса OutputStream , той поддържа възможността за последователно записване на byteове в него.

Ако даден обект имплементира интерфейса Reader , тогава той поддържа възможността за последователно четене на знаци (chars) от него.

Ако даден обект имплементира интерфейса Writer , той поддържа възможността за последователно записване на знаци (символи) в него.

Входно/изходни потоци - 1

Изходният поток е като принтер. Можем да извеждаме documentи на принтера. Можем да извеждаме данни в изходен поток.

От своя страна входният поток може да се сравни със скенер or може би с електрически контакт. Със скенер можем да пренесем documentи на нашия компютър. Или можем да се включим в електрически контакт и да получаваме електричество от него. Можем да получаваме данни от входен поток.

"Къде се използват?"

"Тези класове се използват навсякъде в Java. Нашият познат приятел System.in е статична променлива InputStream , именувана в класа System ."

"Сериозно?! Така че през цялото това време използвах InputStream и дори не го осъзнах. System.out също ли е поток?"

„Да, System.out е статична променлива PrintStream (потомък на OutputStream ) в класа System.“

„Искате да ми кажете, че винаги съм използвал потоци и дори не съм го знаел?“

„Да, и това само ни казва колко удобни са тези потоци. Просто вземете един и го използвайте.“

„Но не можете да кажете това за System.in. Постоянно трябваше да добавяме BufferedReader or InputStreamReader към него.“

— Вярно е. Но имаше и причини за това.

Има много типове данни и много начини за работа с тях. Така че броят на стандартните I/O класове нарасна много бързо, въпреки че те правеха всичко по почти същия начин. За да избегнат тази сложност, разработчиците на Java използваха принципа на абстракцията и разделиха класовете на много малки части.

Но можете да свържете тези части по последователен начин и да получите много сложна функционалност, ако имате нужда от нея. Вижте този пример:

Изведете низ към конзолата
System.out.println("Hello");
Съхранявайте изходния поток на конзолата в отделна променлива.
Изведете низ към потока.
PrintStream console = System.out;
console.println("Hello");
Създайте динамичен (разширяващ се) byteов масив в паметта.
Свържете го с нов изходен поток (обект PrintStream).
Изведете низ към потока.
ByteArrayOutputStream stream = new ByteArrayOutputStream();
PrintStream console = new PrintStream(stream);
console.println("Hello");

„Честно казано, това е като комплект Лего. Само че не ми е ясно Howво прави някой от този code.“

„Не се тревожи за това засега. Всичко на своето време.“

Това е, което искам да запомните: Ако даден клас имплементира интерфейса OutputStream, можете да пишете byteове в него. Почти точно Howто извеждате данни към конзолата. Какво прави с него си е негова работа. С нашия "Лего комплект" ние не се интересуваме от преднаmeaningто на всяка отделна част. Ние се интересуваме от факта, че големият избор от части ни позволява да създаваме такива страхотни неща.

"Добре. Тогава откъде да започнем?"