1. OutputStreamklass

Vi har nyligen utforskat indataströmmar. Det är dags att prata om utgångsströmmar.

Klassen OutputStreamär den överordnade klassen för alla klasser som stöder byte-utdata. Det här är en abstrakt klass som inte gör något på egen hand, men den har efterkommande klasser för varje tillfälle.

Det låter extremt komplicerat. För att uttrycka det enklare, den här klassen fungerar på bytes, och inte till exempel tecken eller andra datatyper. Och det faktum att det är abstrakt betyder att vi vanligtvis inte använder det, utan snarare en av dess efterkommande klasser. Till exempel FileOutputStreamoch liknande.

Men tillbaka till OutputStreamklassen. Den här klassen har metoder som alla dess underliggande klasser måste implementera. Här är de viktigaste:

Metoder Beskrivning
void write(int b)
Skriver en byte (inte en int) till strömmen.
void write(byte[] buffer)
Skriver en array av byte till strömmen
void write(byte[] buffer, off, len)
Skriver en del av en array av byte till strömmen
void flush()
Skriver all data lagrad i bufferten till strömmen
void close()
Stänger strömmen

När du skapar ett objekt av en klass som ärver InputStreamanger du vanligtvis ett källobjekt som InputStreamläser data från. När du skapar ett objekt av en klass som ärver OutputStreamanger du vanligtvis också målobjektet eller strömmen som data ska skrivas till.

Låt oss kort gå igenom klassens alla metoder OutputStream:

write(int b)metod

Denna metod skriver en byte (inte en int) till utgångsströmmen. Det godkända värdet castas till en byte, och int:s första tre byte kasseras.

write(byte[] buffer)metod

Skriver den givna arrayen av byte till utgångsströmmen. Det är allt.

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

Skriver en del av den passerade arrayen av byte till utgångsströmmen. Offsetvariabeln indikerar indexet för det första elementet i matrisen och lengthär längden på delmängden som ska skrivas.

flush()metod

Metoden flush()används för att tvinga all data som potentiellt är buffrad i den aktuella strömmen att skrivas till målströmmen. Detta är relevant när man använder buffring och/eller flera strömobjekt arrangerade i en kedja.

close()metod

Skriver all oskriven data till målobjektet. Metoden close()behöver inte anropas om du använder ett try-with-resourcesblock.

Exempel på kopiering av en fil

Koda Notera
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);
   }
}



InputStreamför att läsa från en fil
OutputStreamför att skriva till en fil

Buffert som vi kommer att läsa in data i
Så länge det finns data i strömmen

Läs data i bufferten
Skriv data från bufferten till den andra strömmen

2. Writerklass

Klassen Writerär exakt samma som OutputStreamklassen, men bara en skillnad igen: den fungerar med tecken ( char) istället för byte.

Det här är en abstrakt klass: du kan inte skapa objekt i Writerklassen. Dess huvudsakliga mål är att vara en gemensam föräldraklass för hundratals efterkommande klasser och att ge dem gemensamma metoder för att arbeta med karaktärsströmmar.

Metoder för Writerklassen (och alla dess underliggande klasser):

Metoder Beskrivning
void write(int b)
Skriver ett tecken (inte ett int) till strömmen.
void write(char[] buffer)
Skriver en rad tecken till strömmen
void write(char[] buffer, off, len)
Skriver en del av en uppsättning tecken till strömmen
void write(String str)
Skriver en sträng till strömmen
void write(String str, off, len)
Skriver en del av en sträng till strömmen
void flush()
Skriver all data lagrad i bufferten till strömmen
void close()
Stänger strömmen

Metoderna är väldigt lika metoderna i klassen, OutputStreammen de fungerar med tecken istället för byte.

Beskrivning av metoder:

write(int b)metod

Denna metod skriver ett enstaka tecken ( char— inte ett int) till utmatningsströmmen. Det godkända värdet kastas till a charoch de första två byten kasseras.

write(char[] buffer)metod

Skriver den givna uppsättningen av tecken till utdataströmmen.

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

Skriver en del av den passerade arrayen av tecken till utdataströmmen. Variabeln offsetindikerar indexet för det första elementet i arrayen och lengthär längden på delmängden som ska skrivas.

write(String str)metod

Skriver den givna strängen till utgångsströmmen.

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

Skriver en del av den givna strängen till utdataströmmen: strängen konverteras till en array av tecken. Variabeln offsetindikerar indexet för det första elementet i arrayen och lengthär längden på delmängden som ska skrivas.

flush()metod

Metoden flush()används för att tvinga all data som potentiellt är buffrad i den aktuella strömmen att skrivas till målströmmen. Detta är relevant när man använder buffring och/eller flera strömobjekt arrangerade i en kedja.

close()metod

Skriver all oskriven data till målobjektet. Metoden close()behöver inte anropas om du använder ett try-with-resourcesblock.

Exempel på ett program som kopierar en textfil:

Koda Notera
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);
   }
}



Readerför att läsa från en fil
Writerför att skriva till en fil

Buffert som vi kommer att läsa in data i
Så länge det finns data i strömmen

Läs data i en buffert
Skriv data från bufferten till den andra strömmen

StringWriterklass

Det finns en annan intressant klass som ärver Writerklassen: den heter StringWriter. Den innehåller en föränderlig sträng — ett StringBufferobjekt. Och varje gång du "skriver" något till objektet StringWriterläggs texten helt enkelt till i dess interna buffert.

Exempel:

Koda Notera
StringWriter writer = new StringWriter();
writer.write("Hello");
writer.write(String.valueOf(123));

String result = writer.toString();
En målteckenström ( StringWriter) skapas
En sträng skrivs till bufferten inuti StringWriter
En sträng skrivs till bufferten inuti StringWriter

Konvertera innehållet i ett objekt till en sträng

I det här fallet StringWriterär klassen i huvudsak ett omslag över StringBufferklassen, men StringWriterklassen är en ättling till Writerströmklassen och den kan användas i kedjor av strömobjekt. Detta är en ganska användbar egenskap i praktiken.



3. PrintStreamklass

Utdataströmsklasser kan också läggas in i en kedja med mellanliggande strömmar som skriver data till målströmmen som skickas till dem. Den allmänna synen på interaktionen mellan dessa strömmar ser ut så här:

Klassen PrintStream

Den mest intressanta och mångsidiga av alla mellanliggande utdataströmmar är PrintStream. Den har tiotals metoder och så många som 12 konstruktörer.

Klassen PrintStreamärver FilterOutputStreamklassen, som ärver OutputStream. Det betyder att PrintStreamklassen har alla metoder för de överordnade klasserna förutom sina egna metoder . Här är de mest intressanta:

Metoder Beskrivning
void print(obj)
Konverterar det skickade objektet till en sträng och matar ut det till målströmmen.
void println(obj)
Konverterar det skickade objektet till en sträng och matar ut det till målströmmen. Lägger till en radbrytning i slutet
void println()
Matar ut ett radbrytningstecken till målströmmen
PrintStream format(String format, args...)
Konstruerar och matar ut en sträng baserat på formatsträngen och de godkända argumenten; liknande String.format()metoden

Och var är dessa tiotals metoder, frågar du dig?

Tja, den har många varianter av print()och println()metoder med olika parametrar. De kan sammanfattas i denna tabell.

Vi kommer inte att fördjupa oss i dessa metoder, eftersom du redan känner till dem väl. Kan du gissa vad jag menar?

Kommer du ihåg System.out.println()? Men det kan skrivas på två rader:

Koda Konsolutgång
PrintStream stream = System.out;
stream.println("Hello!");
Hello!

Vårt favoritkommando är ett anrop till metoden på klassens statiska variabel . Och denna variabels typ är .System.out.println()println()outSystemPrintStream

På många CodeGym-nivåer, och i nästan varje uppgift, har du anropat klassens metoder PrintStreamutan att ens veta om det!

Praktisk användning

Java har denna intressanta klass som heter ByteArrayOutputStream, som är en dynamiskt växande byte-array som ärver OutputStream.

Ett ByteArrayOutputStreamobjekt och PrintStreamobjekt kan kedjas ihop så här:

Koda Beskrivning
ByteArrayOutputStream baos = new ByteArrayOutputStream();

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

String result = baos.toString();

System.out.println(result);
Skapa en skrivbuffert i minnet

Slå in bufferten i ett PrintStreamobjekt

Skriv data till konsolen



Konvertera arrayen till en sträng!

Konsolutgång:
Hello!
123