1. Datastrømmer
Sjelden eksisterer et program som en øy for seg selv. Programmer samhandler vanligvis på en eller annen måte med "verden utenfor". Dette kan skje ved å lese data fra tastaturet, sende meldinger, laste ned sider fra Internett, eller omvendt, laste opp filer til en ekstern server.
Vi kan referere til alle disse atferdene i ett ord: datautveksling mellom programmet og omverdenen. Vent, det er ikke bare ett ord.
Selve datautvekslingen kan selvfølgelig deles inn i to deler: mottak av data og sending av data. For eksempel leser du data fra tastaturet ved hjelp av et Scanner
objekt - dette er å motta data. Og du viser data på skjermen ved å bruke en System.out.println()
kommando - dette er å sende data.
I programmering brukes begrepet "strøm" for å beskrive datautveksling. Hvor kom det begrepet fra?
I det virkelige liv kan du ha en strøm av vann eller en strøm av bevissthet. I programmering har vi datastrømmer .
Strømmer er et allsidig verktøy. De lar programmet motta data fra hvor som helst (inndatastrømmer) og sende data hvor som helst (utdatastrømmer). Dermed er det to typer:
- En inngangsstrøm er for å motta data
- En utdatastrøm er for å sende data
For å gjøre strømmer "håndgripelige", skrev Javas skapere to klasser: InputStream
og OutputStream
.
Klassen InputStream
har en read()
metode som lar deg lese data fra den. Og OutputStream
klassen har en write()
metode som lar deg skrive data til den. De har andre metoder også, men mer om det senere.
Bytestrømmer
Hva slags data snakker vi om? Hvilket format tar det? Med andre ord, hvilke datatyper støtter disse klassene?
Dette er generiske klasser, så de støtter den vanligste datatypen - byte
. En OutputStream
kan skrive byte (og byte-matriser), og et InputStream
objekt kan lese byte (eller byte-matriser). Det er det - de støtter ikke noen andre datatyper.
Som et resultat kalles disse strømmene også bytestrømmer .
En funksjon ved strømmer er at dataene deres bare kan leses (eller skrives) sekvensielt. Du kan ikke lese data fra midten av en strøm uten å lese alle dataene som kommer før den.
Slik fungerer lesing av data fra tastaturet gjennom klassen Scanner
: du leser data fra tastaturet sekvensielt, linje for linje. Vi leser en linje, så neste linje, så neste linje, og så videre. Passende nok heter metoden for å lese linjer nextLine()
.
Å skrive data til en OutputStream
skjer også sekvensielt. Et godt eksempel på dette er konsollutgang. Du skriver ut en linje, etterfulgt av en og en til. Dette er sekvensiell utgang. Du kan ikke skrive ut den første linjen, deretter den tiende og deretter den andre. Alle data skrives kun sekvensielt til en utdatastrøm.
Karakterstrømmer
Du har nylig lært at strenger er den nest mest populære datatypen, og det er de faktisk. Mye informasjon sendes rundt i form av tegn og hele strenger. En datamaskin utmerker seg ved å sende og motta alt som byte, men mennesker er ikke så perfekte.
På grunn av dette, skrev Java-programmerere to klasser til: Reader
og Writer
. Klassen Reader
er analog med InputStream
klassen, men read()
metoden leser ikke bytes, men tegn ( char
). Klassen Writer
tilsvarer klassen OutputStream
. Og akkurat som Reader
klassen fungerer den med tegn ( char
), ikke byte.
Hvis vi sammenligner disse fire klassene, får vi følgende bilde:
Byte (byte) | Tegn (char) | |
---|---|---|
Leser data |
|
|
Skrive data |
|
|
Praktisk anvendelse
Selve InputStream
, OutputStream
, Reader
og Writer
klassene brukes ikke direkte av noen, siden de ikke er assosiert med noen konkrete objekter som data kan leses fra (eller som data kan skrives inn). Men disse fire klassene har nok av etterkommerklasser som kan mye.
2. InputStream
klasse
Klassen InputStream
er interessant fordi den er foreldreklassen for hundrevis av etterkommerklasser. Den har ingen egne data, men den har metoder som alle dens avledede klasser arver.
Generelt er det sjelden at strømobjekter lagrer data internt. En strøm er et verktøy for lesing/skriving av data, men ikke lagring. Når det er sagt, finnes det unntak.
Metoder for InputStream
klassen og alle dens etterkommerklasser:
Metoder | Beskrivelse |
---|---|
|
Leser én byte fra strømmen |
|
Leser en rekke byte fra strømmen |
|
Leser alle bytene fra strømmen |
|
Hopper over n byte i strømmen (leser og forkaster dem) |
|
Sjekker hvor mange byte som er igjen i strømmen |
|
Lukker strømmen |
La oss kort gå gjennom disse metodene:
read()
metode
Metoden read()
leser én byte fra strømmen og returnerer den. Du kan bli forvirret av int
returtypen. Denne typen ble valgt fordi int
er standard heltallstype. De tre første bytene av int
vil være null.
read(byte[] buffer)
metode
Dette er den andre varianten av read()
metoden. Den lar deg lese en byte-array fra en InputStream
alt på en gang. Matrisen som skal lagre bytene må sendes som et argument. Metoden returnerer et tall - antallet byte som faktisk er lest.
La oss si at du har en buffer på 10 kilobyte og at du leser data fra en fil ved hjelp av FileInputStream
klassen. Hvis filen bare inneholder 2 kilobyte, vil alle dataene bli lastet inn i bufferarrayen, og metoden vil returnere tallet 2048 (2 kilobyte).
readAllBytes()
metode
En veldig god metode. Den leser bare alle dataene fra InputStream
til den går tom og returnerer den som en enkeltbyte-array. Dette er veldig nyttig for å lese små filer. Store filer passer kanskje ikke fysisk inn i minnet, og metoden vil gi et unntak.
skip(long n)
metode
Denne metoden lar deg hoppe over de første n bytene fra objektet InputStream
. Fordi dataene leses strengt sekvensielt, leser denne metoden ganske enkelt de første n bytene fra strømmen og forkaster dem.
Returnerer antall byte som faktisk ble hoppet over (i tilfelle strømmen ble avsluttet før n
byte ble hoppet over).
int available()
metode
Metoden returnerer antall byte som fortsatt er igjen i strømmen
void close()
metode
Metoden close()
lukker datastrømmen og frigjør de eksterne ressursene knyttet til den. Når en strøm er stengt, kan ikke flere data leses fra den.
La oss skrive et eksempelprogram som kopierer en veldig stor fil. Vi kan ikke bruke readAllBytes()
metoden til å lese hele filen inn i minnet. Eksempel:
Kode | Merk |
---|---|
|
InputStream for lesing fra filen OutputStream for skriv til fil Buffer som vi skal lese dataene inn i Så lenge det er data i strømmen Les data inn i bufferen Skriv dataene fra bufferen til den andre strømmen |
I dette eksemplet brukte vi to klasser: FileInputStream
er en etterkommer av InputStream
for å lese data fra en fil, og FileOutputStream
er en etterkommer av OutputStream
for å skrive data til en fil. Vi skal snakke om den andre klassen litt senere.
Et annet interessant poeng her er real
variabelen. Når den siste blokken med data leses fra en fil, kan den lett ha mindre enn 64KB med data. Følgelig må vi ikke sende ut hele bufferen, men bare en del av den - de første real
bytene. Det er nettopp dette som skjer i write()
metoden.
3. Reader
klasse
Klassen Reader
er en komplett analog av InputStream
klassen. Den eneste forskjellen er at det fungerer med tegn ( char
), ikke med byte. Akkurat som InputStream
klassen, Reader
brukes ikke klassen noe sted alene: den er overordnet klasse for hundrevis av etterkommerklasser og definerer vanlige metoder for dem alle.
Metoder for Reader
klassen (og alle dens etterkommerklasser):
Metoder | Beskrivelse |
---|---|
|
Leser en char fra strømmen |
|
Leser en char matrise fra strømmen |
|
Hopper over n chars i strømmen (leser og forkaster dem) |
|
Sjekker om det fortsatt er noe igjen i strømmen |
|
Lukker strømmen |
Metodene er veldig like de i InputStream
klassen, selv om det er små forskjeller.
int read()
metode
Denne metoden leser en char
fra strømmen og returnerer den. Typen char
utvides til en int
, men de to første bytene av resultatet er alltid null.
int read(char[] buffer)
metode
Dette er den andre varianten av read()
metoden. Den lar deg lese en char array fra en Reader
alt på en gang. Matrisen som skal lagre tegnene må sendes som et argument. Metoden returnerer et tall – antallet tegn som faktisk er lest.
skip(long n)
metode
Denne metoden lar deg hoppe over de første n tegnene fra objektet Reader
. Det fungerer nøyaktig det samme som den analoge metoden i InputStream
klassen. Returnerer antall tegn som faktisk ble hoppet over.
boolean ready()
metode
Returnerer true
hvis det er uleste byte i strømmen.
void close()
metode
Metoden close()
lukker datastrømmen og frigjør de eksterne ressursene knyttet til den. Når en strøm er stengt, kan ikke flere data leses fra den.
Til sammenligning, la oss skrive et program som kopierer en tekstfil:
Kode | Merk |
---|---|
|
Reader for å lese fra en fil Writer for å skrive til en fil Buffer som vi skal lese dataene inn i Så lenge det er data i strømmen Les data inn i en buffer Skriv dataene fra bufferen til den andre strømmen |
GO TO FULL VERSION