1. OutputStreamklasa

Niedawno zbadaliśmy strumienie danych wejściowych. Czas porozmawiać o strumieniach wyjściowych.

Klasa OutputStreamjest klasą nadrzędną dla wszystkich klas obsługujących wyjście bajtowe. Jest to klasa abstrakcyjna, która sama nic nie robi, ale ma klasy potomne na każdą okazję.

Brzmi to niezwykle skomplikowanie. Upraszczając, ta klasa operuje na bajtach, a nie np. znakach czy innych typach danych. A fakt, że jest abstrakcyjny, oznacza, że ​​zwykle go nie używamy, ale raczej jedną z jego klas potomnych. Na przykład FileOutputStreami tym podobne.

Ale wracając do OutputStreamklasy. Ta klasa ma metody, które muszą implementować wszystkie jej klasy potomne. Oto główne:

Metody Opis
void write(int b)
Zapisuje jeden bajt (nie int) do strumienia.
void write(byte[] buffer)
Zapisuje tablicę bajtów do strumienia
void write(byte[] buffer, off, len)
Zapisuje część tablicy bajtów do strumienia
void flush()
Zapisuje wszystkie dane przechowywane w buforze do strumienia
void close()
Zamyka strumień

Kiedy tworzysz obiekt klasy, która dziedziczy InputStream, zwykle określasz obiekt źródłowy, InputStreamz którego odczytuje dane. Kiedy tworzysz obiekt klasy, która dziedziczy OutputStream, zwykle określasz również obiekt docelowy lub strumień, do którego będą zapisywane dane.

Omówmy pokrótce wszystkie metody klasy OutputStream:

write(int b)metoda

Ta metoda zapisuje jeden bajt (nie int) do strumienia wyjściowego. Przekazana wartość jest rzutowana na bajt, a pierwsze trzy bajty int są odrzucane.

write(byte[] buffer)metoda

Zapisuje podaną tablicę bajtów w strumieniu wyjściowym. Otóż ​​to.

write(byte[] buffer, int offset, int length)metoda

Zapisuje część przekazanej tablicy bajtów do strumienia wyjściowego. Zmienna przesunięcia wskazuje indeks pierwszego elementu tablicy i lengthjest długością podzbioru, który ma zostać zapisany.

flush()metoda

Ta flush()metoda służy do wymuszenia zapisania danych potencjalnie buforowanych w bieżącym strumieniu do strumienia docelowego. Jest to istotne w przypadku korzystania z buforowania i/lub wielu obiektów strumieniowych ułożonych w łańcuch.

close()metoda

Zapisuje wszystkie niezapisane dane w obiekcie docelowym. Metoda close()nie musi być wywoływana, jeśli używasz try-with-resourcesbloku.

Przykład kopiowania pliku

Kod Notatka
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileInputStream input = new FileInputStream(src);
FileOutputStream output = new FileOutputStream(dest))
{
   byte[] buffer = new byte[65536]; // 64Kb
   while (input.available() > 0)
   {
      int real = input.read(buffer);
      output.write(buffer, 0, real);
   }
}



InputStreamdo odczytu z pliku
OutputStreamdo zapisu do pliku

Bufor do którego wczytamy dane
Dopóki w strumieniu są dane

Wczytaj dane do bufora
Zapisz dane z bufora do drugiego strumienia

2. Writerklasa

Klasa Writerjest dokładnie taka sama jak OutputStreamklasa, ale jest jeszcze jedna różnica: działa ze znakami ( char) zamiast bajtami.

To jest klasa abstrakcyjna: nie można tworzyć obiektów tej Writerklasy. Jego głównym celem jest bycie wspólną klasą nadrzędną dla setek klas potomnych i zapewnienie im wspólnych metod pracy ze strumieniami znaków.

Metody klasy Writer(i wszystkich jej klas potomnych):

Metody Opis
void write(int b)
Zapisuje jeden znak (nie int) do strumienia.
void write(char[] buffer)
Zapisuje tablicę znaków w strumieniu
void write(char[] buffer, off, len)
Zapisuje część tablicy znaków do strumienia
void write(String str)
Zapisuje ciąg znaków w strumieniu
void write(String str, off, len)
Zapisuje część ciągu do strumienia
void flush()
Zapisuje wszystkie dane przechowywane w buforze do strumienia
void close()
Zamyka strumień

Metody są bardzo podobne do metod klasy OutputStream, ale działają ze znakami zamiast bajtów.

Opis metod:

write(int b)metoda

Ta metoda zapisuje pojedynczy znak ( char— nie an int) do strumienia wyjściowego. Przekazana wartość jest rzutowana na a char, a pierwsze dwa bajty są odrzucane.

write(char[] buffer)metoda

Zapisuje podaną tablicę znaków w strumieniu wyjściowym.

write(char[] buffer, int offset, int length)metoda

Zapisuje część przekazanej tablicy znaków do strumienia wyjściowego. Zmienna offsetwskazuje indeks pierwszego elementu tablicy i lengthjest długością podzbioru do zapisania.

write(String str)metoda

Zapisuje podany ciąg w strumieniu wyjściowym.

write(String str, int offset, int length)metoda

Zapisuje część podanego ciągu do strumienia wyjściowego: ciąg jest konwertowany na tablicę znaków. Zmienna offsetwskazuje indeks pierwszego elementu tablicy i lengthjest długością podzbioru do zapisania.

flush()metoda

Ta flush()metoda służy do wymuszenia zapisania danych potencjalnie buforowanych w bieżącym strumieniu do strumienia docelowego. Jest to istotne w przypadku korzystania z buforowania i/lub wielu obiektów strumieniowych ułożonych w łańcuch.

close()metoda

Zapisuje wszystkie niezapisane dane w obiekcie docelowym. Metoda close()nie musi być wywoływana, jeśli używasz try-with-resourcesbloku.

Przykład programu kopiującego plik tekstowy:

Kod Notatka
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileReader reader = new FileReader(src);
FileWriter writer = new FileWriter(dest))
{
   char[] buffer = new char[65536]; // 128Kb
   while (reader.ready())
   {
      int real = reader.read(buffer);
      writer.write(buffer, 0, real);
   }
}



Readerdo odczytu z pliku
Writerdo zapisu do pliku

Bufor do którego wczytamy dane
Dopóki w strumieniu są dane

Wczytaj dane do bufora
Zapisz dane z bufora do drugiego strumienia

StringWriterklasa

Jest jeszcze jedna interesująca klasa, która dziedziczy Writerklasę: nazywa się StringWriter. Zawiera zmienny napis — StringBufferobiekt. I za każdym razem, gdy „piszesz” coś do StringWriterobiektu, tekst jest po prostu dodawany do jego wewnętrznego bufora.

Przykład:

Kod Notatka
StringWriter writer = new StringWriter();
writer.write("Hello");
writer.write(String.valueOf(123));

String result = writer.toString();
StringWriterTworzony jest docelowy strumień znaków ( )
Ciąg znaków jest zapisywany w buforze wewnątrz Ciąg StringWriter
znaków jest zapisywany w buforze wewnątrz StringWriter

Konwertowanie zawartościobiektu na ciąg znaków

W tym przypadku StringWriterklasa jest zasadniczo opakowaniem StringBufferklasy, ale StringWriterklasa jest potomkiem Writerklasy strumienia i może być używana w łańcuchach obiektów strumienia. Jest to bardzo przydatna właściwość w praktyce.



3. PrintStreamklasa

Klasy strumieni wyjściowych można również umieścić w łańcuchu ze strumieniami pośrednimi, które zapisują dane w przekazywanym im strumieniu docelowym. Ogólny widok interakcji tych strumieni wygląda następująco:

Klasa PrintStream

Najbardziej interesującym i wszechstronnym ze wszystkich pośrednich strumieni wyjściowych jest PrintStream. Posiada dziesiątki metod i aż 12 konstruktorów.

Klasa PrintStreamdziedziczy FilterOutputStreamklasę, która dziedziczy OutputStream. Oznacza to, że klasa oprócz własnych metodPrintStream ma wszystkie metody klas nadrzędnych . Oto najciekawsze z nich:

Metody Opis
void print(obj)
Konwertuje przekazany obiekt na ciąg i wyprowadza go do strumienia docelowego.
void println(obj)
Konwertuje przekazany obiekt na ciąg i wyprowadza go do strumienia docelowego. Dodaje podział linii na końcu
void println()
Wysyła znak końca wiersza do strumienia docelowego
PrintStream format(String format, args...)
Konstruuje i wyprowadza ciąg na podstawie ciągu formatującego i przekazanych argumentów; podobna do String.format()metody

A gdzie są te dziesiątki metod, pytasz?

Cóż, ma wiele wariantów metod print()i println()o różnych parametrach. Można je podsumować w tej tabeli.

Nie będziemy zagłębiać się w te metody, ponieważ już je dobrze znasz. Domyślasz się, do czego zmierzam?

pamiętasz System.out.println()? Ale można to zapisać w dwóch linijkach:

Kod Wyjście konsoli
PrintStream stream = System.out;
stream.println("Hello!");
Hello!

Naszym ulubionym poleceniem jest wywołanie metody na zmiennej statycznej klasy . Typ tej zmiennej to .System.out.println()println()outSystemPrintStream

Na wielu poziomach CodeGym iw prawie każdym zadaniu wywoływałeś metody klasy, PrintStreamnawet o tym nie wiedząc!

Praktyczne użycie

Java ma tę interesującą klasę o nazwie ByteArrayOutputStream, która jest dynamicznie rosnącą tablicą bajtów, która dziedziczy OutputStream.

Obiekt ByteArrayOutputStreami PrintStreamobiekt można połączyć łańcuchowo w następujący sposób:

Kod Opis
ByteArrayOutputStream baos = new ByteArrayOutputStream();

try(PrintStream stream = new PrintStream(baos))
{
   stream.println("Hello");
   stream.println(123);
}

String result = baos.toString();

System.out.println(result);
Utwórz bufor zapisu w pamięci

Zapakuj bufor w PrintStreamobiekt

Zapisz dane do konsoli



Zamień tablicę na łańcuch!

Wyjście konsoli:
Hello!
123