Poglavje 9
Vhod/izhod

V računalništvu v izrazom vhod/izhod (V/I; angl. input/output ali I/O) označujemo komunikacijsko pot med programom in “zunanjim svetom”. Program preko vhoda dobi vhodne podatke (parametre), izhodne podatke (rezultate) pa sporoči preko izhoda. Poleg standardnega vhoda (običajno s tem izrazom označujemo tipkovnico) lahko program podatke prebere tudi od drugod (na primer: miška, datoteka, spomin, mrežna povezava, ...). Podobno je z zapisovanjem podatkov - poleg standardnega izhoda (zaslon) se podatki lahko, med drugim, zapisujejo tudi na datoteko, tiskalnik, spomin, mrežno povezavo, ... . Java predvideva enoten način dela z vsemi vhodno/izhodnimi napravami - podatki se berejo iz teh naprav in pišejo na te naprave z uporabo t.i. vhodno/izhodnih tokov (angl. input/output streams). Paket java.io predstavlja obširno knjižnico za delo z vhodom in izhodom.

9.1 Znaki in zlogi

9.1.1 ASCII

Ker računalnik v osnovi razume le števila, so vsi znaki (črke) v računalniku predstavljeni s števili. Osnovno tabelo za preslikavo med znaki in števili predstavlja t.i. ASCII tabela. Z njo je zakodiranih 95 znakov (vse črke angleške abecede, cifre, presledek ter znaki !"#%&()*+’-./:;<=>?@[\]^_‘{|}~) ter 33 kontrolnih znakov. Po ASCII tabeli črki ’A’ pripada koda 65, črki ’a’ koda 97, cifri ’0’ koda 48 in podobno. Najpomembnejši kontrolni znaki so

Kontrolni znakPomen ASCII koda






LF skok kurzorja v novo vrsto (line feed) 10



CR skok kurzorja na začetek vrstice (carriage return)13



BELL zvonček 7



BS brisanje prejšnjega znaka (backspace) 8



TAB tabulator 9



DEL brisanje znaka 127
 

Ostali znaki se danes skoraj ne uporabljajo več (definirani so bili z ASCII tabelo v šestdesetih letih prejšnjega stoletja, predvsem za potrebo v teletype (TTY) strojih). ASCII tabela je 7-bitna - v njej je definiranih 128 znakov in kontrol. Ker je to bistveno premalo za kodiranje vseh uporabnih znakov, se leta 1979 standardizirali t.i. razširjeni 8-bitni ASCII tabelo. Prvi del tabele (prvih 128 znakov) se ujema z ASCII tabelo, na mestih od 128 do 255 pa so definirani novi znaki.

9.1.2 Unicode

Seveda tudi 256 znakov, kolikor jih vsebuje razširjena ASCII tabela ni dovolj za predstavitev vseh znakov. V 8-bitni ASCII tabeli tako, na primer, manjkajo sičniki in šumniki (蚞ȊŽ), znaki grške abecede in cirilice ter podobno. Ker je v sodobnem računalniku potreba po omenjenih znakih zelo velika, so začeli razvijati nove standarde, ki bi vsebovali VSE znake. Tako sta nastala standarda UCS in Unicode (omenjena standarda sta usklajena, čeprav jih razvijata dve ločeni ustanovi).

V Unicode standardu je prostora za 216 znakov. Standard se nenehno spreminja - dodajajo se nove črke, stare ostajajo vedno na istih mestih. ASCII tabela je vsebovana v Unicode standardu, zato imajo osnovne črke še vedno iste kode. Spodnja tabela prikazuje Unicode kode za nekatere najbolj pogoste znake.

Znaki Kode (dec) Kode (hex)



a–z 97–122 0061–007A
A–Z 65–90 0041–005A
0–0 48–57 0030–0039
čČšŠžŽ269, 268, 353, 352, 382, 381010d, 010c, 0161, 0160, 017e, 017d

 

Unicode vsebuje sklope po 127 znakov. Vsak sklop ima svoje ime. Za nas so najbolj zanimivi in uporabni znaki so v sklopih Basic Latin (kode med 0000 in 007F - ASCII) ter Latin Extended-A (kode med 0100 in 017F - tu so definirani znaki čČšŠžŽ).

Spodnji program

Izpis ASCII in Latin Extended-A tabele vhodizhod/Tabela.java

 

Za podrobnosti o Unicode glej http://www.unicode.org/ in http://www.lookuptables.com/.

Java popolnoma podpira Unicode. Nekaj primerov uporabe Unicode znakov v Javi prikazuje spodnji program.

 

  char c = \u0078;                   // c  = x 
  int \u0078 = 5;                      // x  = 5; 
 
  // s1 = "a" + x + "z" = "a5z" 
  String s1 = "a" + \u0078 + "z"; 
 
  String s2 = "Ur\u0161a";       // s2 = "Ursa" 
  String s3 = "Ur\\u0161a";      // s3 = "Ur\u0161a"

9.1.3 Kodiranje znakov

Po Unicode standardu vsakemu znaku pripada natančno določena številka. Ker Java v celoti podpira Unicode, je znotraj Jave za vsak znak rezerviranih šestnajst bitov. Vse spremenljivke, nizi in komentarji zato lahko vsebujejo poljuben Unicode znak (na primer znake 蚞ȊŽ, grške črke ali kitajsko pismenko).

Kako pa je z zapisovanjem znakov v datoteko? Ker je po Unicode vsak znak predstavljen s šestnajstimi biti, bi bilo smiselno, če bi pri zapisovanju znakov v datoteko, za vsak znak porabili dva bajta. Tak način zapisovanja je sporen vsaj iz dveh razlogov:

  1. ker ne omogoča kompatibilnosti s starimi “ne Unicode” datotekami; če se uporablja le ASCII standard je vsak znak predstavljen (v spominu in v datoteki) le z enim bajtom in
  2. ker so tako dobljene datoteke v velikem številu primerov predolge. Večino znakov v datotekah so še vedno ASCII znaki (črke, cifre, ...), za katere zadošča po en bajt in jih je zato nesmiselno kodirati z dvema.

Da bi rešili omenjeni dve težavi, so uvedli t.i. kodiranje znakov. Pred zapisovanjem in branjem znakov v/iz datoteke se je potrebno dogovoriti, kako se bo posamezni znak zapisal/prebral.

UTF-16
Najbolj preprost način kodiranja je t.i. UTF-16 kodiranje, pri katerem vsak znak v datoteki zasede dva bajta (Unicode koda). Če datoteka, kodirana z UTF-16, vsebuje same ASCII znake, bo vsak drugi bajt v datoteki enak 0. Ta način je preprost, vendar je prostorsko zelo potraten.

UTF-8
Drugi način kodiranja je t.i. UTF-8, pri katerem so ASCII znaki predstavljeni z enim bajtom, ne ASCII pa z dvema ali tremi bajti. Kodiranje je zelo preprosto vendar učinkovito. UTF-8 je najbolj pogosto uporabljen način kodiranja.

8-bitna kodiranja
Poleg omenjenih kodiranj pa obstaja še vrsto 8-bitnih kodiranj. Za vsako od teh kodiranj obstaja t.i. 8-bitna kodna tabela, v kateri je prvih 128 znakov rezerviranih za ASCII znake, preostalih 128 pa za posebne znake. V kodni tabeli ISO-1250 (Latin2) so med posebnimi znaki tudi znaki 蚞ȊŽ, v kodni tabeli ISO-1251 (Cyrillic) pa so med posebnimi znaki vsi znaki cirilice. Vsak znak se pred zapisom v datoteko v skladu s kodno tabelo pretvori v bajt. Če znaka, ki ga zapisujemo, ni v kodni tabeli, se v datoteko zapiše znak ?. Pri branju poteka postopek ravno obratno. Prebrani bajt se preko kodne tabele pretvori v Unicode znak. Pri tej pretvorbi do napak ne more priti.

Ko podatke pišemo v datoteko, moramo izbrati način kodiranja. Ko podatke beremo, moramo ta način poznati (dekodirati moramo z istim načinom, kot smo kodirali!). Kadar imamo opravka le z datotekami, ki se pišejo in berejo na istem računalniku, do težav praviloma ne more priti. V operacijskem sistemu je namreč določen privzeti način kodiranja in vse datoteke se (če posebej ne zahtevamo drugače), berejo in pišejo na privzet način. Kadar pa imamo opravka z datotekami, ki so nastale na enem, berejo pa se na drugem računalniku (na primer html datoteke) pa je treba posebej določiti način kodiranja. Način je določen bodisi avtomatično (v html datotekah je lahko zapisan v glavi)

<meta HTTP-EQUIV=čontent-type" CONTENT="text/html; charset=UTF-8">

bodisi ga določi uporabnik.

9.1.4 Java razlikuje med znakovnimi in zlogovnimi datotekami

Čeprav so v vsaki datoteki podatki zapisani z zlogi (bajti), Java razlikuje med datotekami, ki vsebujejo znake in datotekami, ki vsebujejo bajte. Pri delu z znakovnimi datotekami Java avtomatsko skrbi za pretvorbo med zlogi in Unicode znaki po izbranem načinu kodiranja. Seveda lahko programer znakovne datoteke bere in piše enako kot zlogovne datoteke, vendar s tem prevzame delo kodiranje in dekodiranja v svoje roke (Java mu pri tem ne pomaga).

Naloga 9-I. Napiši program za izpis zlogov (šestnajstiške kode) datoteke.  

Za branje datoteke bomo uporabili razred FileInputStream - z njim beremo datoteko zlog-to-zlogu.

Rešitev naloge 9-I.: Izpis datoteke po zlogih vhodizhod/Hexdump.java

 

9.2 Razred java.io.File

Razred java.io.File omogoča sistemsko neodvisen dostop do datotečnega sistema. Objekti razreda File se ne uporabljajo za upravljanje z vsebino datoteko, pač pa za upravljanje z datotekami samimi. Objekt razreda File lahko predstavlja datoteko ali direktorij. Primer kreiranja objekta tipa File:

 

  File f  = new File("C:\delo\besedilo.txt"); 
  File p  = new File("C:\delo"); 
  File pd = new File(p,"besedilo.txt);

S pomočjo objekta tipa File lahko preverimo, ali neka datoteka obstaja in ugotovimo njeno velikost, kot je razvidno iz naslednjega primera.

Uporaba metod File.exists() in File.length() vhodizhod/VelikostDatoteke.java

 

 

Nekatere druge metode razreda File so: getName(), getPath(), canWrite(), renameTo(File dest), delete() in mkdir().

9.2.1 Pregledovanje direktorijske strukture

Naloga 9-II. Napiši program, ki izpiše drevo map (podobno, kot dela program tree).  

Rešitev naloge 9-II.: Izpis direktorijske strukture v drevesni obliki vhodizhod/DirTree.java

 

9.3 Tokovi

Tok je zaporedje podatkov. V Javi se tokovi uporabljajo za branje podatkov iz vhoda in za pisanje podatkov na izhod. Vsak vhodni tok ima svoj izvor, vsak izhodni pa svoj ponor.

Kakšna je razlika med podatki, shranjenimi v tabeli in podatki, do katerih dostopamo preko tokov? Če so podatki shranjeni v tabeli, lahko ob kateremkoli času dostopamo do poljubnega podatka (na primer: prvi/zadnji podatek tabele, podatek na sredi tabele, ...). Za dostop do vsakega podatka v tabeli potrebujemo enako časa. Pri podatkih, do katerih dostopamo preko tokov, pa imamo v nekem trenutku dostop samo do tistega podatka, ki se nahaja na čelu toka (trenutni podatek). Tok podatkov lahko primerjamo z vodnim tokom, ki ga opazujemo skozi prozorno okence v sicer neprozorni cevi, ali pa z audio kaseto z glasbo - poslušamo lahko le tisto skladbo, ki je na traku ob bralni glavi kasetofona; če želimo slišati drugo skladbo, moramo kaseto previti naprej ali nazaj, kar pa zahteva nekaj časa. Podobno kot nekateri kasetofoni ne omogočajo previjanja kaset nazaj, tega ne omogočajo nekateri Javanski tokovi.

Javanske tokove lahko primerjamo z vrsto ljudi, ki čakajo na gondolo (jajček za štiri osebe) na smučišču, kjer se dogaja naslednje:

Podobno kot v zgornjem primeru, v se Javanski tok z enega konca bere, na drugem pa podatki lahko šele nastajajo. Če je hitrost branja večja od hitrosti nastajanja podatkov, lahko pride do blokiranja (program se ustavi in čaka dokler se iskani podatek ne pojavi). Tok se konča s posebnim kontrolnim znakom. Pred uporabo moramo tok OBVEZNO odpreti (open), po uporabi pa zapreti (close), sicer ne sprostimo sistemskih virov in lahko pride do neželenih težav (npr. zavrnjen dostop).

Paket java.io vsebuje razrede za delo s podatkovni in znakovni tokovi. Pri podatkovnih tokovih je osnovni podatkovni tip byte (8 bitov), pri znakovnih pa char (16-bitov).

images/tokovi.eps

Posebno skupino tokov predstavljajo t.i. filtrirni tokovi ali filtri. To so tokovi, ki jih vedno uporabimo v kombinaciji z nekim drugim, osnovnejšim tokom. Filter ovije osnovni tok in mu da dodatno funkcionalnost. Tako data filter omogoča pisanje in branje javanskih primitivnih tipov (byte, int, char, ...), buffered filter pa z branjem in pisanjem podatkov preko vmesnega izravnalnega pomnilnika omogoča hitrejše delo z vhodno/izhodnimi tokovi. Print filter (izhodni tok, ki nima vhodnega ekvivalenta) omogoča izpis primitivnih tipov v tekstovni obliki.

9.4 Podatkovni (byte) tokovi

Podatkovni tokovi se uporabljajo za branje/pisanje podatkov (bajtov); podatkovni vhodni tok se imenuje input stream, izhodni pa output stream. Vsi podatkovni tokovi so nasledniki abstraktnih razredov InputStream in OutputStream in implementirajo naslednje metode za branje oziroma pisanje.

 

  int read() throws IOException 
  int read(byte[] b) throws IOException 
  int read(byte[] b, int off, int len) throws IOException 
 
  void write(int b) throws IOException 
  void write(byte[] b) throws IOException 
  void write(byte[] b, int off, int len) throws IOException

 
Vse omenjene metode (read in write) se izvajajo sinhrono, to pomeni, da se klic omenjenih metod konča šele, ko je podatek zares prebran oziroma napisan.

V Javi 1.4 je implementiranih 9 naslednikov abstraktnega razreda InputStream, vsak je specializiran za natančno določen način branja podatkovnih vhodnih tokov. Mi bomo spoznali le najpomembnejše med njimi, in sicer: FileInputStream, DataInputStream, BufferedInputStream in ObjectInputStream. Hkrati z vhodnimi tokovi bomo predstavili tudi njihove izhodne ekvivalente.



Vhodni podatkovni tokovi Izhodni podatkovni tokovi


 
java.lang.Object  
 |  
 +--java.io.InputStream  
    |  
    +--java.io.FileInputStream  
    |  
    +--java.io.FilterInputStream  
    |   |  
    |   +--java.io.DataInputStream  
    |   |  
    |   +--java.io.BufferedInputStream  
    |  
    |  
    |  
    +--java.io.ObjectInputStream  

 
java.lang.Object  
 |  
 +--java.io.OutputStream  
    |  
    +--java.io.FileOutputStream  
    |  
    +--java.io.FilterOutputStream  
    |   |  
    |   +--java.io.DataOutputStream  
    |   |  
    |   +--java.io.BufferedOutputStream  
    |   |  
    |   +--java.io.PrintStream  
    |  
    +--java.io.ObjectOutputStream  



9.4.1 FileInputStream, FileOutputStream

Razredi tipa FileInputStream in FileOutputStream predstavljajo vhodne in izhodne podatkovne tokove, ki so povezani z datotekami. Podatki se berejo in pišejo v datoteke kot zaporedje bajtov.

Razredi tipa FileInputStream se ustvarijo s konstruktorjema oblike

 

  FileInputStream(String name) throws FileNotFoundException 
  FileInputStream(File file) throws FileNotFoundException

Če datoteka, s katero želimo povezati tok, ne obstaja, konstruktor vrže izjemo tipa FileNotFoundException. Konstruktorji za FileOutputStream so

 

  FileOutputStream(String name) throws FileNotFoundException 
  FileOutputStream(String name, boolean append) throws FileNotFoundException 
  FileOutputStream(File file) throws IOException

Če datoteka že obstaja, se bo ob klicu konstruktorja resetirala (vsebina se pobriše), razen v primeru drugega konstruktorja, kjer lahko povemo, da se vsebina datoteki dodaja. Če datoteka pred klicem ne obstaja, se naredi nova datoteka s podanim imenom. Če želimo pisati v datoteko, pa za to nimamo pravic, konstruktor vrže izjemo SecurityException. Primer uporabe FileOutputStream vidimo v spodnjem programu.

V datoteko zapisemo tri bajte vhodizhod/WriteBytes.java

 

9.4.2 DataInputStream in DataOutputStream

Tokova DataInputStream in DataOutputStream se uporabljata za branje in pisanje Javanskih osnovnih podatkovnih tipov: boolean, char, byte, short, int, long, float, double in String.

DataOutputStream lahko ovijemo okoli poljubnega toka tipa OutputStream (na primer FileOutputStream), DataInputStream pa okoli poljubnega toka tipa InputStream (na primer FileInputStream).

Primer uporabe toka tipa DataOutputStream (vhodizhod/Dos.java):

Če poženemo zgornji program, bo datoteka podatki.dat vsebovala naslednje 16-bitne besede (izpis s programom Hexdump):


01 20 00 41 01 D7 00 61 00 62 00 63 00 64 00 04 61 62 63 64 00 00 00 20


Razlaga: boolean se zapiše kot byte (00 ali 01), char kot 16-bitni Unicode znak, niz kot zaporedje 16-bitnih Unicode znakov, int kot 32-bitov.

Primer uporabe toka tipa DataInputStream (vhodizhod/Dis.java):

9.4.3 BufferedInputStream in BufferedOutputStream

Tokova BufferedInputStream in BufferedOutputStream sta posebna filtra, ki zelo pohitrita vhodno/izhodne operacije. Poskrbita namreč, da se podatki ne berejo oziroma pišejo posamezno (zlog po zlogu), pač pa večjih sklopih. Buffered filtra ustvarita kopijo dela toka (npr. datoteke) v spominu, tako, da branje in pisanje v resnici pomeni branje in pisanje v spomin (kar je veliko hitreje kot, na primer, branje in pisanje v datoteko). Seveda tokova poskrbita, da se po končanju pisanja in branja vsi podatki iz spomina pravilno zapišejo na mesto, kamor spadajo (na primer na disk). Buffered filtri se vedno uporabljajo v kombinaciji z nekim drugim filtrom (na primer z Data filtrom).

Primer uporabe toka tipa BufferedOutputStream:

Primer uporabe toka tipa BufferedInputStream:

Tokova dos in dis iz zgornjih primerov uporabimo na enak način kot v primerih pri DataInputStream in DataOutputStream. Ko smo med File in Data filter vstavili še Buffered filter, da končni (Data) filter ni spremenil. Spremenila se je le hitrost vseh vhodno/izhodnih operacij.

9.4.4 ObjectInputStream in ObjectOutputStream

Serializacija objektov je postopek, ki omogoča pretvorbo objektov v zaporedje zlogov iz katerih lahko kasneje rekonstruiramo (deserializiramo) originalni objekt. Omenjeni postopek med drugim uporabljamo za prenos objektov z uporabo tokov. Če želimo torej nek objekt zapisati v datoteko (da ga bomo lahko kasneje prebrali in obnovili), ga moramo najprej serializirati in zapisati na ustrezen izhodni tok. Da lahko izvedemo omenjen postopek, morata biti izpolnjena naslednja dva pogoja:

  1. razred objekta, ki ga želimo shraniti, mora implementirati vmesnik Serializable.
  2. tok, v katerega bomo pisali serializiran objekt, mora implementirati vmesnik ObjectOutput.

Primeren tok za zapis serializiranih objektov je ObjectOutputStream, za branje pa ObjectInputStream. Poleg objektov lahko z omenjenima tokovoma, podobno kot s tokovoma tipa Data, pišemo (beremo) osnovne podatkovne tipe (boolean, byte, char, ...) ter znake v 16-bitnem Unicode kodiranju (metodi writeChars() in readLine()) in UTF kodiranju (metodi writeUTF(), readUTF()).

Naloga 9-III. Napiši razred Oseba, v katerem hraniš podatke (ime, priimek in starost) o neki osebi. Napiši razred Imenik, ki omogoča pisanje in branje objektov tipa Oseba.  

Rešitev naloge 9-III.: Branje in pisanje oseb v imenik vhodizhod/Imenik.java

 

9.5 Znakovni (char) tokovi

Znakovni tokovi se uporabljajo za branje/pisanje človeku razumljivih znakov (16-bitne unicode črke); znakovni vhodni tok je reader, izhodni pa writer.

9.5.1 InputStreamReader in BufferedReader

InputStreamReader se uporablja za branje znakov iz datoteke. Uporabnik lahko določi način kodiranja, ki se pri tem uporablja. Če uporabnik kodiranja ne določi eksplicitno, se uporabi privzeto kodiranje.

Nekatere metode:  

  public String getEncoding() // vrne ime kodiranja, ki se 
                              // uporablja pri tem branju 
  public int read()           // prebere naslednji znak 
  public boolean ready()      // true ce naslednji klic read() 
                              // ne zablokira programa

Nekateri konstruktorji:  

  InputStreamReader(InputStream in) 
  InputStreamReader(InputStream in, String charsetName)

BufferedReader je ovojni tok za nek reader. Omogoča hitrejše branje podatkov (uporaba medpomnilnika). Poleg branja znakov (metoda read()) BufferedReader omogoča tudi branje celotnih vrstic s pomočjo metode readLine().

Primer uporabe:  

BufferedReader in 
   = new BufferedReader(new InputStreamReader(System.in));

9.5.2 OutputStreamWriter in BufferedWriter

OutputStreamWriter uporabljamo za pisanje znakov v datoteko. Pri tem se znaki zakodirajo z izbranim načinom kodiranja. Če način kodiranja ni podan eksplicitno, se uporabi privzeti način.

Nekatere metode:  

  public String getEncoding() // vrne ime kodiranja, ki se 
                              // uporablja pri tem branju 
  public void write(int c)    // zapise znak 
  public void close()         // zapre tok

Nekateri konstruktorji:  

  public OutputStreamWriter(OutputStream out) 
  public OutputStreamWriter(OutputStream out, Charset cs)

Priporočena je uporaba BufferedWriter ovojnega toka  

    Writer out 
       = new BufferedWriter(new OutputStreamWriter(System.out));

Naloga 9-IV. Napiši program, ki omogoča pretvorbo iz enega v drug kodirni sistem. Ime vhodne in izhodne datoteke ter imena obeh kodirnih sistemov so podani kot argumenti ob klicu programa.  

Rešitev naloge 9-IV.: Pretvorba med različnimi kodirnimi sistemi vhodizhod/Pretvornik.java

 

9.5.3 FileReader in FileWriter

Razreda FileReader in FileWriter predstavljata poenostavitev razredov InputStreamReader in OutputStreamWriter. Oba uporabita privzet način kodiranja, poleg tega se FileWriter in FileReader sama povežeta z datoteko.

Preprosta konstruktorja:  

  public FileReader(String fileName) 
  public FileWriter(String fileName)

Uporabljamo enake metode kot pri InputStreamReader in OutputStreamWriter.

9.5.4 Scanner

Razred Scanner uporabljamo za branje besedila in razbijanje prebranega besedila na posamezne dele. Pri ločevanju besedila Scanner uporablja ločilo (delimiter), ki ga uporabnik lahko spremeni. Privzeto ločilo: TAB, PRESLEDEK, NOVA_VRSTA (whitespaces). Posamezne dele besedila zna Scanner pretvoriti v primitivne tipe.

Primer branja celega števila iz standardnega vhoda:  

  Scanner sc = new Scanner(System.in);\\ 
  int i = sc.nextInt();\\

Nekateri konstruktorji:

 

 
  public Scanner(File source)  // scanner povezez z datoteko 
  public Scanner(File source, String charset) // povezez z datoteko in 
                                              // podas nacin kodiranja 
  public Scanner(InputStream source) // scanner povezez s tokom 
  public Scanner(String source)      // branje podatkov  iz niza

Nekatere metode:  

    public boolean hasNextLine() 
    public byte nextLine() 
 
    public boolean hasNextInt() 
    public int nextInt()

Naloga 9-V. V datoteki zemljevid.txt so podani podatki o koordinatah slovenskih mest.

0 0 Koper  
70 70 Ljubljana  
110 30 Novo mesto  
50 90 Skofja Loka  
25 110 Jesenice  
140 140 Maribor  
170 150 Murska Sobota

Napiši program, ki to datoteko prebere, nato pa od uporabnika v zanki zahteva vpis imena mesta; za vsako prebrano mesto naj program izpiše koordinate.  

Rešitev naloge 9-V.: Koordinate kraja vhodizhod/Zemljevid.java

 

9.5.5 PrintWriter

PrintWriter je ovojni tok. Uporabljamo ga za izpisovanje osnovnih podatkovnih tipov v tekstovni obliki. Podatki se zakodirajo s kodirnim načinom, ki ga uporablja oviti tok.

Nekateri konstruktorji:  

 // ovijemo tok tipa OutputStream;  uporablja se 
 // sistemsko privzeti nacin kodiranja 
 PrintWriter(OutputStream out); 
 
 // ovijemo tok tipa Writer (na primer OutputStreamWriter), 
 // pri katerem lahko dolocimo nacin kodiranja 
  PrintWriter(Writer out)

Nekatere metode:  

  public void print(char c) 
  public void print(int i) 
  public void print(float f) 
  public void println(char c)

9.5.6 Branje iz tipkovnice

Branje iz tipkovnice je posebni primer branja iz datoteke. Uporabimo lahko vse zgoraj opisane razrede in tokove, razlika je le v tem, da kot osnovni tok uporabimo System.in.

 

  // sc uporabim za branje iz datoteke 
  Scanner sc = new Scanner(new File("datoteka.txt")); 
 
  // sc uporabim za branje iz tipkovnice 
  Scanner sc = new Scanner(System.in);

9.5.7 Branje podatkov iz interneta

Podobno kot branje iz tipkovnice je tudi branje datoteke, ki se nahaja nekje na svetovnem spletu, poseben primer branja datoteke. V primeru branja podatkov iz interneta za osnovni tok, okoli katerega potem ovijamo namenske tokove, uporabimo tok, ki ga vrne metoda openStream() razreda URL.

 

    URL url = new URL("http://kepa.fri.uni-lj.si/index.html"); 
    Scanner sc = new Scanner(url.openStream());

Z objektom sc delamo na enak način, kot če bi bil povezan z lokalnim izvorom podatkov.

Naloga 9-VI. Napiši program, ki izpiše trenutno temperaturo v Ljubljani. Podatke o temperaturi preberi s strani http://www.gozdis.si/meteo/vreme_lj2.htm.  

Rešitev naloge 9-VI.: Prikaz temperature v Ljubljani vhodizhod/Temperatura.java