JavaRush /Blog Java /Random-PL /Czytanie z klawiatury – „czytelnicy”

Czytanie z klawiatury – „czytelnicy”

Opublikowano w grupie Random-PL
Cześć! Na wykładach i zadaniach nauczyliśmy się wyprowadzać dane do konsoli i odwrotnie – odczytywać dane z klawiatury. Czytanie z klawiatury - „czytelnicy” - 1Nauczyłeś się nawet używać do tego złożonej konstrukcji:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Ale nadal nie odpowiedzieliśmy na jedno pytanie.

Jak to w ogóle działa?

W rzeczywistości każdy program najczęściej nie istnieje samodzielnie. Może komunikować się z innymi programami, systemami, Internetem itp. Przez słowo „komunikować” mamy na myśli przede wszystkim „wymianę danych”. Oznacza to, że odbierz trochę danych z zewnątrz, a wręcz przeciwnie, wyślij gdzieś własne dane. Przykładów wymiany danych pomiędzy programami jest wiele, nawet w życiu codziennym. Dlatego w wielu witrynach zamiast się rejestrować, możesz zalogować się przy użyciu konta na Facebooku lub Twitterze. W tej sytuacji dwa programy, powiedzmy Twitter i witryna, na której próbujesz się zarejestrować, wymieniają między sobą niezbędne dane, po czym widzisz efekt końcowy - pomyślną autoryzację. Termin „ przepływ ” jest często używany do opisania procesu wymiany danych w programowaniu . Skąd w ogóle wzięła się ta nazwa? „Przepływ” bardziej kojarzy się z rzeką lub strumieniem niż z programowaniem. W sumie nie bez powodu :) Strumień to w istocie poruszająca się porcja danych. Oznacza to, że w programowaniu to nie woda „płynie” wzdłuż strumienia, ale dane w postaci bajtów i znaków. Ze strumienia danych możemy otrzymać dane w częściach i coś z nimi zrobić. Ponownie użyjmy analogii z „płynącą wodą”: można czerpać wodę z rzeki, aby ugotować zupę, ugasić ogień lub podlać kwiaty. Korzystając ze strumieni, możesz pracować z dowolnym źródłem danych: Internetem, systemem plików Twojego komputera lub czymś innym - to nie ma znaczenia. Strumienie są narzędziem uniwersalnym. Pozwalają programowi odbierać dane z dowolnego miejsca (strumienie przychodzące) i wysyłać je w dowolne miejsce (strumienie wychodzące). Ich zadanie jest jedno – zebrać dane w jednym miejscu i wysłać je w drugie. Strumienie dzielą się na dwa typy:
  1. Strumień przychodzący ( Input ) - używany do odbierania danych
  2. Strumień wychodzący ( Wyjście ) - do wysyłania danych.
Przychodzący przepływ danych w Javie jest zaimplementowany w klasie InputStream, a wychodzący przepływ danych w klasie OutputStream. Istnieje jednak inny sposób podziału wątków. Dzielą się one nie tylko na przychodzące i wychodzące, ale także na bajtowe i znakowe . Tutaj znaczenie jest jasne i nie wymaga wyjaśnienia: strumień bajtów przesyła informacje w postaci zestawu bajtów, a strumień znaków przesyła informacje w postaci zestawu znaków. W tym wykładzie szczegółowo omówimy strumienie przychodzące. A na koniec dołączę informację o linkach wychodzących, o czym możecie przeczytać sami :) A więc nasz kod:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Czytając wykłady pewnie pomyśleliście, że wygląda to dość przerażająco? :) Ale to tylko do czasu, aż dowiemy się, jak to działa. Naprawmy to teraz! Zacznijmy od końca. System.injest obiektem klasy InputStream, o której mówiliśmy na początku. Jest to strumień przychodzący, powiązany z urządzeniem wejściowym systemu – klawiaturą. Nawiasem mówiąc, pośrednio go znasz. W końcu często wykorzystujesz jego „kolegę” w swojej pracy - System.out! System.out- jest to systemowy strumień wyjściowy danych , służy do wyprowadzenia danych do konsoli tą samą metodą System.out.println(), której stale używasz :) System.out- strumień do wysyłania danych do konsoli oraz System.in- do odbierania danych z klawiatury. To proste :) Ponadto: aby odczytać dane z klawiatury, możemy obejść się bez tej dużej konstrukcji i po prostu napisać: System.in.read();
public class Main {

   public static void main(String[] args) throws IOException {

       while (true) {
           int x = System.in.read();
           System.out.println(x);
       }
   }
}
W klasie InputStream(a System.in, przypomnę, jest obiektem klasy InputStream) znajduje się metoda read()pozwalająca na odczyt danych. Jeden problem: czyta bajty , a nie znaki . Spróbujmy odczytać z klawiatury rosyjską literę „Ya”. Wyjście konsoli:
Я
208
175
10
Litery rosyjskie zajmują 2 bajty w pamięci komputera (w przeciwieństwie do liter angielskich, które zajmują tylko 1). W tym przypadku ze strumienia zostały odczytane 3 bajty: pierwsze dwa reprezentują naszą literę „I”, a drugi to przerwanie wiersza (Enter). Dlatego opcja użycia „nago” System.innie będzie nam odpowiadać. Ludzie (z rzadkimi wyjątkami!) nie mogą czytać bajtów. I tu z pomocą przychodzi nam kolejna klasa – InputStreamReader! Zastanówmy się, jakie to zwierzę.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
Przekazujemy strumień System.indo InputStreamReader. Ogólnie rzecz biorąc, jeśli przetłumaczysz jego nazwę na rosyjski, wszystko wydaje się oczywiste - „czytnik przychodzących strumieni”. Właściwie, właśnie po to jest! Tworzymy obiekt klasy InputStreamReaderi przekazujemy mu przychodzący strumień, z którego powinien odczytać dane. W tym przypadku...
new InputStreamReader(System.in)
...mówimy mu: „odczytasz dane z systemowego strumienia wejściowego (klawiatura).” Ale to nie jedyna jego funkcja! InputStreamReadernie tylko odbiera dane ze strumienia. Konwertuje także strumienie bajtów na strumienie znaków . Innymi słowy, nie musisz się już martwić tłumaczeniem odczytanych danych z języka „komputerowego” na język „ludzki” – InputStreamReaderwszystko zrobi za Ciebie. InputStreamReaderoczywiście potrafi czytać dane nie tylko z konsoli, ale także z innych miejsc. Przykładowo z pliku:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

   public static void main(String[] args) throws IOException {
       InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\username\\Desktop\\testFile.txt"));
   }
}
Tutaj utworzyliśmy przychodzący strumień danych FileInputStream(jest to jedna z odmian InputStream), przekazaliśmy do niego ścieżkę do pliku i przekazaliśmy sam strumień InputStreamReader„y. Teraz będzie mógł odczytać dane z tego pliku, jeśli oczywiście plik pod tą ścieżką istnieje. Aby odczytać dane (nieważne skąd, z konsoli, pliku czy gdziekolwiek indziej), klasa InputStreamReaderużywa również metody read(). Jaka jest różnica między System.in.read()i InputStreamReader.read()? Spróbujmy policzyć tę samą literę „I” za pomocą InputStreamReader. Przypomnę, myślałem tak System.in.read():
Я
208
175
10
Jak on może wykonywać tę samą pracę InputStreamReader?
public class Main {

   public static void main(String[] args) throws IOException {

       InputStreamReader reader = new InputStreamReader(System.in);
       while (true) {
           int x = reader.read();
           System.out.println(x);
       }
   }
}
Wyjście konsoli:
Я
1071
10
Różnica jest natychmiast widoczna. Ostatni bajt – dla łamania linii – pozostał niezmieniony (cyfra 10), natomiast odczytana litera „I” została zamieniona na pojedynczy kod „1071”. To jest czytanie symbolami! Jeśli nagle nie wierzysz, że kod 1071 oznacza literę „I”, możesz to łatwo zweryfikować :)
import java.io.IOException;

public class Main {

   public static void main(String[] args) throws IOException {

       char x = 1071;
       System.out.println(x);
   }
}
Wyjście konsoli:

Я
Ale skoro InputStreamReaderjest tak dobrze, po co potrzeba więcej BufferedReader? InputStreamReadermoże zarówno czytać dane, jak i konwertować bajty na znaki - czego jeszcze potrzebujemy? Dlaczego kolejny Czytelnik? :/ Odpowiedź jest bardzo prosta – dla większej produktywności i większej wygody . Zacznijmy od wydajności. Podczas odczytu danych BufferedReader korzysta ze specjalnego obszaru – bufora, w którym „dodaje” odczytane znaki. Dzięki temu, gdy będziemy potrzebować tych znaków w programie, zostaną one pobrane z bufora, a nie bezpośrednio ze źródła danych (klawiatura, plik itp.), a to oszczędza mnóstwo zasobów. Aby zrozumieć jak to działa wyobraźmy sobie na przykład pracę kuriera w dużej firmie. Kurier siedzi w biurze i czeka na przyniesienie mu przesyłek do doręczenia. Za każdym razem, gdy otrzymuje nową przesyłkę, może od razu wyruszyć w drogę. Ale w ciągu dnia może być dużo przesyłek i za każdym razem będzie musiał podróżować między biurem a adresami. Zamiast tego kurier umieścił w biurze skrzynkę, do której każdy mógł wrzucić swoje przesyłki. Teraz kurier może spokojnie zabrać paczkę i udać się pod adresy – zaoszczędzi mnóstwo czasu, bo nie będzie musiał za każdym razem wracać do biura. Pudełko w tym przykładzie jest właśnie buforem, a biuro jest źródłem danych. Kurierowi o wiele łatwiej jest wyjąć list ze wspólnej skrzynki podczas jego doręczania, niż za każdym razem udawać się do urzędu. Oszczędzi to także benzynę. Podobnie jest w programie – pobieranie danych z bufora wymaga znacznie mniej zasobów niż każdorazowy dostęp do źródła danych. Dlatego BufferedReader+ InputStreamReaderdziała szybciej niż tylko InputStreamReader. Poprawiliśmy wydajność, ale co z wygodą? Główną zaletą jest to, że BufferedReaderpotrafi czytać dane nie tylko po jednym znaku na raz (chociaż read()ma też metodę do tego celu), ale także całe linie! Odbywa się to za pomocą readLine();
public class Main {

   public static void main(String[] args) throws IOException {

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
       String s = reader.readLine();
       System.out.println(„Czytamy tę linię z klawiatury:”);
       System.out.println(s);
   }
}
Wyjście konsoli:
JavaRush to najlepsza strona do nauki języka Java!
Мы считали с клавиатуры эту строку:
JavaRush — лучший сайт для изучения Java!
Jest to szczególnie przydatne podczas odczytu dużej ilości danych. Nadal można odczytać znak po znaku jedną lub dwie linijki tekstu. Ale liczenie „Wojny i pokoju” po literze będzie nieco problematyczne :) Teraz praca wątków stała się dla Ciebie znacznie bardziej przejrzysta. Do dalszych badań mamy dla Ciebie dodatkowe źródło: Tutaj możesz przeczytać więcej o przepływach przychodzących i wychodzących. Recenzja wideo BufferedReaderjednego z naszych uczniów. Tak, tak, nasi uczniowie nie tylko uczą się sami, ale także nagrywają filmy edukacyjne dla innych! Nie zapomnijcie polubić i zasubskrybować nasz kanał :)
Do czytania oficjalnej dokumentacji lepiej już od samego początku przyzwyczajać się. Jest to główne źródło wiedzy o języku i zawsze można tam znaleźć większość odpowiedzi.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION