Deo zbornika Učimo Javu

Čitanje ulaznog toka

Email Twitter LinkedIn Facebook Google

Osnovna metoda read() iz klase InputStream čita pojedinačni neoznačeni bajt podataka i vraća njegovu int vrijednost.

public abstract int read() throws IOException

Vraća broj između 0 i 255. Kad naiđe na kraj toka, vraća -1, i to koristimo kao zastavicu koja nam govori da smo došli do kraja toka.

Primer: Čitanje unosa

Evo jednog jednostavnog programa koji vraća kao eho korisnikov unos na komandnoj liniji.

import java.io.*;

public class Eho {

  public static void odjek(InputStream ulaz) {
    try {
      while (true) {
        int broj = ulaz.read();   // cita bajt i vraca broj izmedju 0 i 255
        if (broj == -1) break;

        char znak = (char) broj;  // pretvara broj u znak
        System.out.print(znak);    
      }
    }
    catch (IOException e) {
      System.err.println(e);
    }
  }

  public static void main(String[] args) {
    odjek(System.in);
  }
}

Pokretanje iz konzole:

% javac Eho.java
% java Eho
ehooo
ehooo
<Ctrl-C>

Ovaj program neće pravilno raditi sa Unicode znakovima. Svaki bajt se prije ispisa pretvara u ekvialentni ISO Latin-1 znak. Za ne-ASCII znakove koristiti klase java.io.Reader i java.io.Writer.

Čitanje niza bajtova

Dok osnovna read() metoda čita bajt po bajt, sljedeće dvije overloaded varijante čitaju niz bajtova:

public int read(byte[] data) throws IOException
public int read(byte[] data, int offset, int length) throws IOException

Prva metoda čita onoliko bajtova koliko joj treba da napuni niz data. Druga čita onoliko bajtova iz ulaznog strima koliko je zadano u argumentu length i sprema ih u niz počevši od pozicije offset.

Te su metode blokirane dok ne stignu raspoloživi podaci. Tada učitaju onoliko podataka koliko je predviđeno. Nakon toga vraćaju broj bajtova koje su učitale. Ne smijete pretpostaviti da će uvijek biti učitano koliko treba. Ako naiđe kraj toka, vraća se -1.

Brojanje dostupnih bajtova

Metoda available() ispituju koliko bajtova sa uzlaznog toka je spremno za učitavanje bez blokiranja.

public int available() throws IOException

Na primjer, sljedeći program je efikasnija verzija prethodnog programa Eho, jer koristi metodu available() za ispitivanje koliko bajtova je spremno za učitavanje, a zatim kreira niz točno te veličine, učitava bajtove u niz i pretvara ga u strunu koju zatim ispisuje.

import java.io.*;

public class EfikasniEho {

  public static void odjek(InputStream ulaz) {
    try {
      while (true) {
        int n = ulaz.available();
        if (n > 0) {
          byte[] b = new byte[n];
          int rezultat = ulaz.read(b);
          if (rezultat == -1) break;
          String s = new String(b);
          System.out.print(s);
        } // if   
      } // while
    } // try
    catch (IOException e) {
      System.err.println(e);
    }
  }

  public static void main(String[] args) {
    odjek(System.in);
  }
}
% javac EfikasniEho.java
% java EfikasniEho
bla bla
bla bla
<Ctrl-C>

Preskakanje bajtova

Metoda skip() čita i odbacuje specificirani broj bajtova.

public int skip(long n) throws IOException

Možete je koristiti, na primjer, ako želite brzo proći standardni header ili prefiks nekih podataka. U sljedećem fragmentu koda koristi se skip() za preskakanje praznina uključenih u DataInputStream dis.

case 171: // lookupswitch
   pad = 3 - (position % 4);
   dis.skip(pad);
   defaultByte = dis.readInt();
   int npairs = dis.readInt();
   result = position + "    lookupswitch " + defaultByte + " " + npairs;
   for (int i = 0; i < npairs; i++) {
     int newPosition = position + pad + 12 + i*8;
     result += "\n" + newPosition + "    " + dis.readInt() + " " + dis.readInt();
   }

Markiranje položaja i reset

Često je korisno ako možete učitati nekoliko bajtova, a zatim se vratiti natrag i učitati ih ponovo. Na primjer, pri oblikovanju nekog kompajlera ne možete znati da li trebate učitati znak <, <<, ili <<= sve dok ne učitate dva ili više bajtova. Bilo bi korisno ako biste se mogli vratiti natrag i ponovo učitati token nakon što ste okrili o kojem se radi.

Neki, ali ne svi tokovi dopuštaju vam da markirate određenu poziciju u toku i onda se vratite na nju. To se radi pomoću sljedećih metoda:

public synchronized void mark(int readlimit)
public synchronized void reset() throws IOException
public boolean markSupported()

Metoda markSupported() vraća true ako taj tok podržava markiranje, a false inače. Pod pretpostavkom da je markiranje podržano, metoda mark() stavlja bookmark na mjesto gdje se kasnije želite vratiti pomoću metode reset(). U jednom toku može postojati samo jedan takav bookmark. Sljedeće markiranje izbrisat će prethodno. Ako markiranje nije podržano, ove će metode izbaciti IOException.

Izvor: Elliotte Rusty Harold, Java Lecture Notes, preveo Draško Budin, priredio Damjan Pavlica.