Guide til Java OutputStream

1. Oversikt

I denne opplæringen vil vi utforske detaljer om Java-klassen OutputStream. OutputStream er en abstrakt klasse. Dette fungerer som superklassen for alle klasser som representerer en utgangsstrøm av byte.

Vi vil undersøke hva disse ordene som "output" og "stream" betyr i flere detaljer når vi går videre.

2. Kort introduksjon til Java IO

OutputStream er en del av Java IO API som definerer klasser som kreves for å utføre I / O-operasjoner i Java. Disse er alle pakket i java.io navneområdet. Dette er en av kjernepakkene som er tilgjengelige i Java siden versjon 1.0.

Ved å starte Java 1.4 har vi også Java NIO pakket i navneområdet java.nio som muliggjør ikke-blokkerende inngangs- og utgangsoperasjoner. Vårt fokusområde for denne artikkelen er imidlertid ObjectStream som en del av Java IO.

Detaljer relatert til Java IO og Java NIO finner du her.

2.1. Inngang og utgang

Java IO gir i utgangspunktet en mekanisme for å lese data fra en kilde og skrive data til en destinasjon. Input representerer kilden mens output representerer destinasjonen her.

Disse kildene og destinasjonene kan være alt fra filer, rør til nettverkstilkoblinger.

2.2. Strømmer

Java IO gir konseptet med strømmer som i utgangspunktet representerer en kontinuerlig datastrøm. Strømmer kan støtte mange forskjellige typer data som byte, tegn, objekter, etc.

Videre er tilkobling til en kilde eller en destinasjon det en strøm representerer. De kommer derfor som begge InputStream eller OutputStream henholdsvis.

3. Grensesnitt av OutputStream

OutputStream implementerer en haug med grensesnitt som gir noen tydelig karakter til underklassene. La oss gå gjennom dem raskt.

3.1. Lukkbar

Grensesnittet Lukkbar gir en metode som kalles Lukk() hvilken håndterer stenging av en kilde eller en destinasjon med data. Hver implementering av OutputStream må gi en implementering av denne metoden. Her kan de utføre handlinger for å frigjøre ressurser.

3.2. Kan lukkes automatisk

Grensesnittet Kan lukkes automatisk gir også en metode som kalles Lukk() med lignende oppførsel som den i Lukkbar. I dette tilfellet imidlertid metode Lukk() kalles automatisk når du avslutter en prøve-med-ressurs-blokk.

Flere detaljer angående prøve-med-ressurs finner du her.

3.3. Flushable

Grensesnittet Flushable gir en metode som kalles flush () som håndterer skylledata til en destinasjon.

En bestemt implementering av OutputStream kan velge å buffer tidligere skrevne byte for å optimalisere, men en samtale til flush () får den til å skrive til destinasjonen umiddelbart.

4. Metoder i OutputStream

OutputStream har flere metoder som hver implementeringsklasse må implementere for sine respektive datatyper.

Disse er bortsett fra Lukk() og flush () metoder som den arver fra Lukkbar og Flushable grensesnitt.

4.1. skriv (int b)

Vi kan bruke denne metoden til å skriv en bestemt byte til OutputStream. Siden argumentet "int" består av fire byte, er par-kontrakten bare den første lavordens-byten skrevet og de resterende tre høy-orden-bytene og ignorert:

offentlig statisk ugyldig filOutputStreamByteSingle (strengfil, strengdata) kaster IOException {byte [] bytes = data.getBytes (); prøv (OutputStream ut = ny FileOutputStream (fil)) {out.write (byte [6]); }}

Hvis vi kaller denne metoden med data som “Hello World!”, Får vi som resultat en fil med følgende tekst:

W

Dette er, som vi kan se, det syvende tegnet i strengen indeksert sjette.

4.2. skriv (byte [] b, int av, int lengde)

Denne overbelastede versjonen av skrive() metoden er der for skriv en undersekvens av byteoppstillingen til OutputStream.

Den kan skrive "lengde" antall byte fra byte-matrisen som spesifisert av argumentet som starter ved en forskyvning bestemt av "av" til OutputStream:

offentlig statisk ugyldig filOutputStreamByteSubSequence (strengfil, strengdata) kaster IOException {byte [] bytes = data.getBytes (); prøv (OutputStream ut = ny FileOutputStream (fil)) {out.write (byte, 6, 5); }}

Hvis vi nå kaller denne metoden med samme data som før, får vi følgende tekst i utdatafilen:

Verden

Dette er undergrunnen for dataene våre som starter ved indeks fem og består av fem tegn.

4.3. skriv (byte [] b)

Dette er enda en overbelastet versjon av skrive() metode som kan skriv et helt byte-utvalg som spesifisert av argumentet til OutputStream.

Dette har samme effekt som en oppfordring til skriv (b, 0, b.lengh):

offentlig statisk ugyldig filOutputStreamByteSequence (strengfil, strengdata) kaster IOException {byte [] bytes = data.getBytes (); prøv (OutputStream ut = ny FileOutputStream (fil)) {out.write (byte); }}

Når vi kaller denne metoden nå med samme data, har vi hele String i vår utdatafil:

Hei Verden!

5. Direkte underklasser av OutputStream

Nå skal vi diskutere noen av de direkte kjente underklassene til OutputStream som hver for seg representerer en spesifikk datatype som OutputStream definerer de.

De definerer sine egne metoder bortsett fra å implementere de arvet fra OutputStream.

Vi vil ikke gå nærmere inn på detaljene i disse underklassene.

5.1. FileOutputStream

Som navnet antyder, a FileOutputStream er en OutputStream å skrive data til en Fil. FileOutputStream, som alle andre OutputStream, kan skrive en strøm av rå byte.

Vi har allerede undersøkt forskjellige metoder i FileOutputStream som en del av den siste delen.

5.2. ByteArrayOutputStream

ByteArrayOutputStream er en Implementering av OutputStream som kan skrive data i et byte-utvalg. Bufferen fortsetter å vokse som ByteArrayOutputStream skriver data til den.

Vi kan beholde standard startstørrelse på bufferen som 32 byte eller angi en bestemt størrelse ved hjelp av en av konstruktørene som er tilgjengelige.

Det viktige å merke seg her er at metoden Lukk() har praktisk talt ingen effekt. De andre metodene i ByteArrayOutputStream kan trygt kalles selv etter Lukk() har blitt kalt.

5.3. FilterOutputStream

OutputStream skriver primært en byte-strøm til en destinasjon, men den kan like godt transformere dataene før du gjør det. FilterOutputStream representerer superklasse av alle slike klasser som utfører en spesifikk datatransformasjon. FilterOutputStream er alltid konstruert med en eksisterende OutputStream.

Noen av eksemplene på FilterOutputStream er BufferedOutputStream, CheckedOutputStream, CipherOutputStream, DataOutputStream, DeflaterOutputStream, DigestOutputStream, InflaterOutputStream, PrintStream.

5.4. ObjectOutputStream

ObjectOutputStream kan skrive primitive datatyper og grafer over Java-objekter til en destinasjon. Vi kan konstruere en ObjectOutputStream bruker en eksisterende OutputStream for å skrive til et bestemt mål som File.

Vær oppmerksom på at det er nødvendig for gjenstander å implementere Serialiserbar til ObjectOutputStream å skrive dem til en destinasjon. Du finner mer informasjon om Java Serialization her.

5.5. PipedOutputStream

EN PipedOutputStream er nyttig for å lage et kommunikasjonsrør. PipedOutputStream kan skrive data som en tilkoblet PipedInputStream kan lese.

PipedOutputStream har en konstruktør for å koble den til en PipedInputStream. Alternativt kan vi gjøre dette senere ved å bruke en metode gitt i PipedOutputStream kalt koble().

6. OutputStream Buffering

Inngangs- og utgangsoperasjoner involverer vanligvis relativt dyre operasjoner som disktilgang, nettverksaktivitet, etc. Å utføre dette ofte kan gjøre et program mindre effektivt.

Vi har "bufrede strømmer" av data i Java for å håndtere disse scenariene. BufferedOutputStreamskriver data til en buffer i stedet som skylles til destinasjonen sjeldnere, når bufferen blir full, eller metoden flush () er kalt.

BufferedOutputStream strekker FilterOutputStream diskutert tidligere og pakker inn en eksisterende OutputStream å skrive til en destinasjon:

offentlig statisk ugyldig bufferedOutputStream (strengfil, streng ... data) kaster IOException {try (BufferedOutputStream out = new BufferedOutputStream (new FileOutputStream (file))) {for (String s: data) {out.write (s.getBytes () ); out.write ("" .getBytes ()); }}}

Det kritiske punktet å merke seg er at hver samtale til skrive() for hvert dataargument skriver bare til bufferen og resulterer ikke i en potensielt kostbar samtale til filen.

I tilfelle ovenfor, hvis vi kaller denne metoden med data som “Hei”, “Verden!”, Vil dette bare resultere i at data blir skrevet til filen når koden går ut av prøve-med-ressurs-blokken som kaller metoden. Lukk()BufferedOutputStream.

Dette resulterer i en utdatafil med følgende tekst:

Hei Verden!

7. Skrive tekst med OutputStreamWriter

En byte-strøm, som diskutert tidligere, representerer rådata som kan være en haug med teksttegn. Nå kan vi få karakterarrangementet og utføre konverteringen til byte-arrayet selv:

byte [] byte = data.getBytes ();

Java tilbyr praktiske klasser for å bygge bro over dette gapet. For saken om OutputStream, denne klassen er OutputStreamWriter. OutputStreamWriter pakker inn en OutputStream og kan skrive tegn direkte til ønsket destinasjon.

Vi kan også velge å tilby OutputStreamWriter med tegnsett for koding:

offentlig statisk ugyldig utgangStreamWriter (strengfil, strengdata) kaster IOException {try (OutputStream out = new FileOutputStream (file); Writer writer = new OutputStreamWriter (out, "UTF-8")) {writer.write (data); }}

Nå som vi kan se, trenger vi ikke å utføre transformasjonen av tegnmatrisen til bytematrisen før vi bruker den FileOutputStream.OutputStreamWriter gjør dette beleilig for oss.

Ikke overraskende når vi kaller metoden ovenfor med data som "Hello World!", Resulterer dette i en fil med tekst som:

Hei Verden!

8. Konklusjon

I denne artikkelen diskuterte vi Java-abstraktklassen OutputStream. Vi gikk gjennom grensesnittene den implementerer og metodene den gir.

Så diskuterte vi noen av underklassene til OutputStream tilgjengelig på Java. Vi snakket til slutt om buffering og karakterstrømmer.

Som alltid er koden for eksemplene tilgjengelig på GitHub.