I/O Streamy


Materiály

Stream

Pro použití streamů je nutné provést import balíčku java.io.

    
    import java.io.*;
    

Stream můžeme definovat jako sekvenci dat. V Javě máme dva typy streamů:

Mezi základní třídy patří InputStream, OutputStream, Reader a Writer. Dále exitují bufferované varianty BufferedInputStream, BufferedOutputStream, BufferedReader a BufferedWriter. U bufferovaných je dostupná metoda flush(), která vyprázdní buffer. Pokud stream už není potřeba tak je dobré jej zavřít pomocí metody close(). Pokud použijeme konstrukci try-with-resources tak je stream uzavřen automaticky.

Bytové streamy

Pro provedení vstupu a výstupu se používají bloky o velikosti 1B. Nejpoužívanějsí třídy jsou FileInputStream a FileOutputStream. Následující příklad ukazuje jak překopírovat obsah jednoho souboru do druhého.

    
    import java.io.*;
    public class CopyFile {

       public static void main(String args[]) throws IOException {
          FileInputStream in = null;
          FileOutputStream out = null;

          try {
             in = new FileInputStream("input.txt");
             out = new FileOutputStream("output.txt");

             int c;
             while ((c = in.read()) != -1) {
                out.write(c);
             }
          } finally {
             if (in != null) {
                in.close();
             }
             if (out != null) {
                out.close();
             }
          }
       }
    }

    // Pomocí try-with-recourses
    public static void main(String[] args) {

        try (FileInputStream in = new FileInputStream("input.txt");
             FileOutputStream out = new FileOutputStream("output.txt")) {

            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

Znakové streamy

Pro provedení vstupu a výstupu se používá 16-bit Unicode. Nejpoužívanějsí třídy jsou FileReader a FileWriter. FileReader interně používá FileInputStream ale čte po 2B a FileWriter interně používá FileOutputStream ale zapisuje po 2B. Následující příklad ukazuje jak překopírovat obsah jednoho souboru do druhého.

    
    import java.io.*;
    public class CopyFile {

       public static void main(String args[]) throws IOException {
          FileReader in = null;
          FileWriter out = null;

          try {
             in = new FileReader("input.txt");
             out = new FileWriter("output.txt");

             int c;
             while ((c = in.read()) != -1) {
                out.write(c);
             }
          } finally {
             if (in != null) {
                in.close();
             }
             if (out != null) {
                out.close();
             }
          }
       }
    }

    // Pomocí try-with-recourses
    public static void main(String[] args) {

        try (FileReader in = new FileReader("input.txt");
             FileWriter out = new FileWriter("output.txt")) {

            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

Třída Scanner

    
    import java.io.*;
    import java.util.Scanner;

    public static void main(String[] args) throws IOException {
        Scanner scanner = null;

        try {
            scanner = new Scanner(new BufferedReader(new FileReader("input.txt")));

            while (scanner.hasNext()) {
                System.out.println(scanner.next());
            }
        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
    }

    // Pomocí try-with-recourses
    public static void main(String[] args) {

        try (Scanner scanner = new Scanner(new BufferedReader(new FileReader("input.txt")))) {
            while (scanner.hasNext()) {
                System.out.println(scanner.next());
            }
        } catch (FileNotFoundException e) {
            System.err.println(e.getMessage());
        }
    }

    

Úkoly

  1. Napište metodu int[][] readTextMatrix(String fileName), která načte z textového souboru matici celých čísel. Jednotlivé řádky souboru představují řádky matice, jednotlivé hodnoty v řádku jsou odděleny mezerou. Pokud dojde k chybě, metoda by měla vyvolat vyjímku.

  2. Upravte předchozí metodu tak, aby její argument byl Reader, tj. int[][] readTextMatrix(Reader r). Vyzkoušejte, že jí lze předat objekt třídy FileReader i StringReader.

  3. Napište metodu void writeTextMatrix(String fileName, int[][] matrix), která zapíše do textového souboru matici celých čísel. Jednotlivé řádky souboru představují řádky matice, jednotlivé hodnoty v řádku jsou odděleny mezerou. Pokud dojde k chybě, metoda by měla vyvolat vyjímku.

  4. Upravte předchozí metodu tak, aby její argument byl Writer. Vyzkoušejte, že jí lze předat objekt třídy FileWriter i StringWriter.

  5. Napište metodu void writeBinaryMatrix(OutputStream s, int[][] matrix), která zapíše do streamu matici celých čísel, hodnoty zapisujte v jejich binarní podobě. Zvolte si vhodný formát. Metodu napište tak, aby byla schopná pracovat s různými typy streamů.

  6. Napište metodu int[][] readBinaryMatrix(InputStream s), která načte matici celých čísel vytvořenou předchozí metodou.

Úkoly posílejte na email r.vyjidacek@gmail.com s předmětem ZP3JV09. Termín odevzdání do půlnoci 29. 11. 2017. Odevzdávejte pouze zdrojové kódy v archivu zip.