CodeGym /Blog Java /Random-PL /Przećwicz pracę z klasami BuffrededReader i InputStreamRe...
Autor
Jesse Haniel
Lead Software Architect at Tribunal de Justiça da Paraíba

Przećwicz pracę z klasami BuffrededReader i InputStreamReader

Opublikowano w grupie Random-PL
Cześć! Dzisiejsza lekcja zostanie dla wygody podzielona na dwie części. Powtórzymy kilka starych tematów, które poruszaliśmy wcześniej, i rozważymy kilka nowych funkcji :) Zacznijmy od pierwszego. Masz już zajęcia jak BufferedReaderwiele razy. Mam nadzieję, że nie miałeś czasu zapomnieć o tym stwierdzeniu:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Zanim zaczniesz czytać dalej, spróbuj sobie przypomnieć, za co odpowiada każdy składnik — System.in, InputStreamReader, — i dlaczego jest potrzebny. BufferedReaderCzy pamiętasz? Jeśli nie, nie martw się. :) Jeśli o czymś zapomniałeś, przeczytaj ponownie tę lekcję , która jest poświęcona zajęciom z czytania. Pokrótce przypomnimy, co potrafi każdy z nich. System.in— jest to strumień do odbierania danych z klawiatury.  W zasadzie samo wystarczyłoby zaimplementować logikę wymaganą do czytania tekstu. Ale, jak pamiętasz, System.inmoże odczytywać tylko bajty, a nie znaki:

public class Main {

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

       while (true) { 
           int x = System.in.read(); 
           System.out.println(x); 
       } 
   } 
} 
Jeśli wykonamy ten kod i wprowadzimy cyrylicę „Й”, wynik będzie następujący:

Й
208
153
10 
Znaki cyrylicy zajmują 2 bajty w pamięci i są wyświetlane na ekranie. Liczba 10 jest dziesiętną reprezentacją znaku wysuwu wiersza, tj. od naciśnięcia Enter. Czytanie bajtów to taka przyjemność, więc używanie System.innie jest zbyt wygodne. Aby poprawnie odczytać litery cyrylicy (i inne), używamy InputStreamReaderjako opakowania:

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); 
       } 
   } 
} 
Wpisujemy tę samą literę „Й”, ale tym razem wynik jest inny:

Й 
1049 
10
InputStreamReaderprzekonwertował dwa bajty (208 i 153) na pojedynczą liczbę 1049. To właśnie oznacza odczytywanie znaków. 1049 odpowiada cyrylicy „Й”. Łatwo możemy się przekonać, że to prawda:

public class Main { 

   public static void main(String[] args) throws IOException { 
       char x = 1049; 
       System.out.println(x); 
   } 
} 
Wyjście konsoli:

Й
I ponieważ forBufferedReader(i ogólnie BufferedAnythingYouWant), klasy buforowane są używane do optymalizacji wydajności. Dostęp do źródła danych (pliku, konsoli, zasobu sieciowego) jest dość kosztowny pod względem wydajności. Dlatego, aby ograniczyć liczbę dostępów, BufferedReaderodczytuje i gromadzi dane w specjalnym buforze, a stamtąd je pobieramy. W rezultacie liczba dostępów do źródła danych jest zmniejszona — prawdopodobnie o kilka rzędów wielkości! Kolejną BufferedReaderjego cechą i jej przewagą nad zwykłą InputStreamReader, jest niezwykle pomocna readLine()metoda, która odczytuje całe wiersze danych, a nie pojedyncze liczby. Jest to oczywiście bardzo wygodne w przypadku dużych tekstów. Oto jak wygląda czytanie wierszy:

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 ("The user entered the following text:"); 
       System.out.println(s); 
       reader.close(); 
   } 
}

BufferedReader+InputStreamReader is faster than InputStreamReader alone 
The user entered the following text: 
BufferedReader+InputStreamReader is faster than InputStreamReader alone
Przećwicz pracę z klasami BuffreredReader i InputStreamReader - 2Oczywiście BufferedReaderjest bardzo elastyczny. Nie jesteś ograniczony do pracy z klawiaturą. Na przykład możesz odczytywać dane bezpośrednio z sieci, po prostu przekazując wymagany adres URL do czytnika:

public class URLReader { 

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

       URL oracle = new URL("https://www.oracle.com/index.html"); 
       BufferedReader in = new BufferedReader( 
               new InputStreamReader(oracle.openStream())); 

       String inputLine; 
       while ((inputLine = in.readLine()) != null) 
           System.out.println(inputLine); 
       in.close(); 
   } 
}
Możesz odczytać dane z pliku, przekazując ścieżkę do pliku:

public class Main { 

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

       FileInputStream fileInputStream = new FileInputStream("testFile.txt"); 
       BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream)); 

       String str; 

       while ((str = reader.readLine()) != null)   { 
           System.out.println (str); 
       } 

       reader.close(); 
   } 
}

Wymiana pliku System.out

Przyjrzyjmy się teraz interesującej możliwości, o której wcześniej nie mówiliśmy. Jak zapewne pamiętasz, Systemklasa ma dwa pola statyczne — System.ini  System.out. Ci bracia bliźniacy to obiekty strumieniowe. System.injest InputStream. I System.out jest PrintStream. W tej chwili porozmawiamy o  System.out. Jeśli przejdziemy do Systemkodu źródłowego klasy, zobaczymy to:

public final class System { 
……………... 
public final static PrintStream out = null; 
 ………… 
} 
Zatem  System.out  jest po prostu zwykłą zmienną statyczną klasySystem . Nie ma w tym nic magicznego :) outZmienna jest PrintStreamreferencją. Oto interesujące pytanie: kiedy System.out.println()jest wykonywane, dlaczego dokładnie dane wyjściowe trafiają do konsoli, a nie gdzie indziej? I czy da się to jakoś zmienić? Załóżmy na przykład, że chcemy odczytać dane z konsoli i zapisać je do pliku tekstowego. Czy można to jakoś zaimplementować po prostu przy użyciu  System.outzamiast dodatkowych klas czytelników i pisarzy? Rzeczywiście jest :) I możemy to zrobić, mimo że System.outzmienna jest oznaczona modyfikatorem final!  Przećwicz pracę z klasami BuffrededReader i InputStreamReader - 3Czego więc potrzebujemy, aby tak się stało? Przede wszystkim potrzebujemy nowego PrintStreamobiektu, który zastąpi obecny. Bieżący obiekt, ustawiony wSystemclass domyślnie nie służy naszym celom: wskazuje na konsolę. Musisz utworzyć nowy, który wskazuje plik tekstowy — „miejsce docelowe” dla naszych danych. Po drugie, musimy zrozumieć, jak przypisać nową wartość do System.outzmiennej. Nie możesz użyć prostego operatora przypisania, ponieważ zmienna jest oznaczona final. Pracujmy wstecz od końca. Tak się składa, że System​​klasa ma metodę, której potrzebujemy: setOut(). Pobiera PrintStreamobiekt i ustawia go jako miejsce docelowe dla danych wyjściowych. Właśnie tego potrzebujemy! Pozostało tylko stworzyć PrintStreamobiekt. To też jest łatwe:

PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
Pełny kod będzie wyglądał następująco:

public class SystemRedirectService { 

   public static void main(String arr[]) throws FileNotFoundException 
   { 
       PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
       /* Save the current value of System.out in a separate variable so that later 
       we can switch back to console output */ 

       PrintStream console = System.out; 
       // Assign a new value to System.out 
       System.setOut(filePrintStream); 
       System.out.println("This line will be written to the text file"); 

       // Restore the old value of System.out 
       System.setOut(console); 
       System.out.println("But this line will be output to the console!"); 
   } 
}
W rezultacie pierwszy ciąg jest zapisywany do pliku tekstowego, a drugi jest wyświetlany w konsoli :) Możesz skopiować ten kod do swojego IDE i uruchomić go. Otwórz plik tekstowy, a zobaczysz, że napis został tam pomyślnie zapisany :) Na tym nasza lekcja dobiegła końca. Dzisiaj przypomnieliśmy sobie, jak pracować ze strumieniami i czytnikami. Przypomnieliśmy sobie, czym się od siebie różnią i poznaliśmy kilka nowych możliwości System.out, z których korzystaliśmy na prawie każdej lekcji :) Do następnych lekcji!
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION