S používáním vstupů a výstupů se při programování setkáváme na každém kroku: výpis na obrazovku, čtení ze souboru, síťová komunikace … V Javě se pro tento účel používá tzv. proudů–streamů. Tento článek vás seznámí s mechanismem vstupně výstupních proudů, ukážeme si, jak se pracuje se soubory, povíme si o standardním vstupu a výstupu a o řetězení proudů.

Balíček java.io obsahuje dvě základní třídy – vstupní proud InputStream (z toho můžete v programu číst data) a výstupní proud OutputStream (do toho naopak data zapisujete). Tento balíček obsahuje množství dalších proudů, které po těchto dvou dědí a používají se pro nějaký specifický účel. Většinou je z názvu třídy patrné, zda se jedná o vstupní (DataInputStream, FileInputStream, BufferedInputStream) nebo výstupní třídu (DataOutputStream, FileOutputStream, BufferedOutputStream).

Čtení ze souboru

Pro čtení ze souboru se používá třída FileInputStream (soubor je pro program vstupem). Jeden z jejich konstruktorů přebírá jako parametr jméno souboru. Takto tedy lze otevřít soubor pro čtení:

FileInputStream vstup = new FileInputStream(”c:\\data\\soubor.txt”);

Všimněte si dvojitých zpětných lomítek (jednoduché zpětné lomítko má speciální význam).

Obdobně se pracuje s třídou FileOutputSteram, která slouží pro zápis do souboru. Použití obou tříd si ukážeme na jednoduchém příkladu, který kopíruje soubor (podobně jako příkaz DOSu copy).

Příklad 1: kopírování souboru

Třída copy otevře jeden soubor pro čtení (jméno předáno prvním parametrem) a jeden soubor pro zápis (jméno předáno druhým parametrem). Obsah prvního souboru zkopíruje do souboru druhého. Metoda available() třídy FileInputStream vrací počet bytů, které jsou na vstupním proudu k dospozici. Metoda read pak čte data ze vstupního proudu do pole bytů a metoda write(byte[]) třídy FileOutputStream naopak pole bytů do výstupního proudu zapisuje.

copy.java:

import java.io.*;
public class copy {
  public copy() {
  }
  public static void main(String[] args) {
    if (args.length<2) {
      System.out.println(„Syntaxe: java copy <soubor1> <soubor2>“);
      return;
    }
    InputStream vstup = null;
    OutputStream vystup = null;
    // otevření prvního souboru pro čtení a založení vstupního proudu
    try {
      vstup = new FileInputStream(args[0]);
    } catch (IOException e) {
      System.out.println(„Soubor „+args[0]+“ se nepodarilo otevrit!“);
      return;
    }
      // otevření druhého souboru pro zápis a založení výstupního proudu
    try {
      vystup = new FileOutputStream(args[1]);
      } catch (IOException e) {
        System.out.println(„Soubor „+args[1]+“ se nepodarilo vytvorit!“);
        return;
      }
    // kopírování obsahu souboru
    byte data[] = new byte[1024];
    int pocet;
    try {
      while (vstup.available()>0) {
        pocet = vstup.read(data);
        vystup.write(data, 0, pocet);
      }
    }
    catch (IOException ex) {
      System.out.println(„Nastala chyba pri kopirovani souboru!“);
    }
  }
}

Standardní proudy

Již v úvodních dílech seriálu jsme se setkávali s voláním

System.out.println(„ahoj“);

Jedná se také o použití proudu. Třída System má statickou proměnnou typu PrintStream (potomek OutputStream) s názvem out, která implementuje metodu println a reprezentuje standardní výstup programu. Podobně můžeme používat proud System.in pro standardní vstup a System.err pro chybový výstup.

Řetězení proudů

Základní třídy InputStream a OutputStream implementují pouze metody pro čtení/zápis bytu nebo pole bytů. Pokud potřebujete v programu číst/zapisovat proměnné jiného typu, máte k dispozici proudy DataInputStream a DataOutputStream. Na existující vstupní proud je automaticky napojíte voláním konstruktoru:

InputStream is = …vstupní proud, který máte k dispozici
DataInputStream dis = new DataInputStream(is);

Tím můžete ke čtení dat použít i jiné metody.

int i = dis.readInt();
double d = dis.readDouble();

Podobně je možné řetězit výstupní proudy, takto např. zapíšete do souboru:

try {
  FileOutputStream xfos = new FileOutputStream(„c:\\vystup.txt“);   // otevře soubor pro zápis
  DataOutputStream dos = new DataOutputStream(xfos);
  dos.writeChars(„Zdravi Interval.“);
  dos.writeInt(5);
  dos.writeInt(10);
}
catch (IOException ex) { … }

Metoda writeChars zapisuje do souboru řetězec ve formátu UNICODE (jeden znak do dvou bytů), metoda writeUTF zapisuje řetězec osmibytově (každý znak jeden byte), metoda writeInt zapisuje do 4 bytů proměnnou typu int, dále existují metody writeBoolean, writeDouble, writeShort, writeLong, …

Existuje rovněž symetrická třída DataInputStream s metodami readInt, readChars, readLong, readBoolean, …

V příštím díle budeme s ukázkami použití proudů pokračovat. Dozvíte se, jak vytvářet filtry, jak bufferovat výstupy.

1 Příspěvěk v diskuzi

Odpovědět