Ανάγνωση Γραφή αρχείων (I/O)

Η Java προσφέρει μια σειρά από κλάσεις για ανάγνωση - γραφή από ή προς ένα αρχείο.

Το αρχείο μπορεί να είναι ένα αρχείο κειμένου (text file) ή ένα δυαδικό αρχείο (binary file).

Η java επίσης προσφέρει κλάσεις για ανάγνωση ή γραφή χαρακτήρα-χαρακτήρα ή γραμμή-γραμμή από ένα αρχείο.

Γενικά έχουμε:

  • Character streams: Όλες οι κλάσεις για character streams προέρχονται από τις υπερκλάσεις Reader και Writer.
  • Byte streams: Όλες οι κλάσεις για byte streams προέρχονται από τις υπερκλάσεις InputStream και OutputStream.
  • Buffered byte streams: Για Buffered byte streams χρησιμοποιούνται οι κλάσεις BufferedInputStream και BufferedOutputStream
  • Buffered character streams: Για Buffered character streams οι BufferedReader και BufferedWriter

Δομή κλάσεων και υποκλάσεων για streaming.

Byte streams

OutputStream FileOutputStream BufferedOutputStream InputStream FileInputStream BufferedInputStream

Character streams

Writer BufferedWriter OutputStreamWriter FileWriter Reader BufferedReader InputStreamReader FileReader

Γραφή αρχείου (output)

Για γραφή αρχείου byte-byte μπορούμε να χρησιμοποιήσουμε τη κλάση FileOutputStream η οποία είναι υποκλάση της OutputStream.

import java.io.FileOutputStream;
import java.io.IOException;

public class WriteBytes {
    public static void main(String[] args) throws IOException {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream("data.dat");
            byte b = 123;
            out.write(b);
            b = 89;
            out.write(b);
        }
        catch(IOException e){
            System.out.print(e.getMessage());
        }
        finally {
            if(out != null) {
                out.close();
            }
        }
    }    
}

Ανάγνωση αρχείου (input)

Για ανάγνωση αρχείου byte-byte μπορούμε να χρησιμοποιήσουμε τη κλάση FileInputStream η οποία είναι υποκλάση της InputStream.

Παράδειγμα με FileInputStream

import java.io.FileInputStream;
import java.io.IOException;

public class ReadBytes {
    public static void main(String[] args) throws IOException {
        FileInputStream in = null;
        try {
            in = new FileInputStream("data.dat");
            byte c;
            while ((c = (byte) in.read()) != -1) {
                System.out.print(c);
            }
        }
        catch(IOException e){
            System.out.print(e.getMessage());
        }
        finally {
            if(in != null) {
                in.close();
            }
        }
    }
}

Γραφή αρχείου χαρακτήρων (output)

Για γραφή αρχείου χαρακτήρα-χαρακτήρα μπορούμε να χρησιμοποιήσουμε την κλάση FileWriter.

import java.io.FileWriter;
import java.io.IOException;

public class WriteCharacters {
    public static void main(String[] args) throws IOException {

        FileWriter out = null;

        try {
            out = new FileWriter("text.txt");
            int c;
            c = 'H';
            out.write(c);
            c = 'o';
            out.write(c);
            c = 'l';
            out.write(c);
            c = 'a';
            out.write(c);
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }
}

Ανάγνωση αρχείου χαρακτήρων (input)

Για γραφή ανάγνωση χαρακτήρα-χαρακτήρα μπορούμε να χρησιμοποιήσουμε την κλάση FileReader.

import java.io.FileReader;
import java.io.IOException;

public class ReadCharacters {
    public static void main(String[] args) throws IOException {

        FileReader in = null;

        try {
            in = new FileReader("text.txt");

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

Γραφή αρχείου κειμένου (γραμμή-γραμμή)

Για γραφή αρχείου γραμμή-γραμμή μπορούμε να χρησιμοποιήσουμε τη κλάση FileWriter και BufferedWriter.

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class WriteTextLines {
    public static void main(String[] args) throws IOException {
        
        FileWriter fw = null;
        BufferedWriter bw = null;
        
        try {
            fw = new FileWriter("textlines.txt");
            bw = new BufferedWriter(fw);
            
            String L = "hello world";
            bw.write(L);
            bw.newLine();
            L = "hola mundo";
            bw.write(L);
            bw.newLine();
            L = "γεια σου κοσμε";
            bw.write(L);            
        } 
        catch(IOException e) {
            System.out.print(e.getMessage());
        }
        finally {
            if (bw != null) {
                bw.close();
            }
        }
    }
}

Ανάγνωση αρχείου κειμένου (γραμμή-γραμμή)

Για ανάγνωση αρχείου γραμμή-γραμμή μπορούμε να χρησιμοποιήσουμε τη κλάση FileReader και BufferedReader.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadTextLines {
    public static void main(String[] args) throws IOException {
        
        FileReader fr = null;
        BufferedReader br = null;
        
        try {
            fr = new FileReader("textlines.txt");
            br = new BufferedReader(fr);
            String L = "";

            while((L = br.readLine()) != null) {
                System.out.println(L);
            }
        } catch(IOException e) {
            System.out.print(e.getMessage());
        }
        finally {
            if(br != null) {
                br.close();
            }
        }
    }
}

Data Streams

Με τα Data Streams μπορούμε να κάνουμε stream δυαδικά δεδομένα πρωταρχικών τύπων (boolean, char, byte, short, int, long, float, double και String)

Οι κλάσεις που χρησιμοποιούμε είναι η DataInputStream και η DataOutputStream οι οποίες υλοποιούν τις διεπαφές DataInput και DataOutput αντίστοιχα.

Βασικές μέθοδοι που χρησιμοποιούμε είναι:

Output Method

DataOutputStream DataOutputStream.writeDouble DataOutputStream.writeInt DataOutputStream.writeUTF DataOutputStream.writeByte DataOutputStream.writeBoolean

Input Method

DataInputStream DataInputStream.readDouble DataInputStream.readInt DataInputStream.readUTF DataInputStream.readByte DataInputStream.readBoolean

Στο παρακάτω παράδειγμα φαίνεται η γραφή και ανάγνωση δεδομένων από ένα σετ εγγραφών.

import java.io.*;
import java.io.IOException;
import java.io.EOFException;

public class DataStreams {
    static final String dataFile = "invoicedata.dat";
    static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 };
    static final int[] units = { 12, 8, 13, 29, 50 };
    static final String[] descs = { "Java T-shirt",
            "Java Mug",
            "Duke Juggling Dolls",
            "Java Pin",
            "Java Key Chain" };
 
    public static void main(String[] args) throws IOException {
 
        DataOutputStream out = null;
         
        try {
            out = new DataOutputStream(new
                    BufferedOutputStream(new FileOutputStream(dataFile)));
 
            for (int i = 0; i < prices.length; i ++) {
                out.writeDouble(prices[i]);
                out.writeInt(units[i]);
                out.writeUTF(descs[i]);
            }
        } finally {
            out.close();
        }
 
        DataInputStream in = null;
        double total = 0.0;
        try {
            in = new DataInputStream(new
                    BufferedInputStream(new FileInputStream(dataFile)));
 
            double price;
            int unit;
            String desc;
 
            try {
                while (true) {
                    price = in.readDouble();
                    unit = in.readInt();
                    desc = in.readUTF();
                    System.out.format("You ordered %d units of %s at $%.2f%n",
                            unit, desc, price);
                    total += unit * price;
                }
            } 
            catch (EOFException e) { 
                
            }
            System.out.format("For a TOTAL of: $%.2f%n", total);
        }
        finally {
            in.close();
        }
    }
}

Object Streams

Με τα Object Streams μπορούμε να κάνουμε stream objects.

Οι κλάσεις που χρησιμοποιούμε είναι η ObjectInputStream και η ObjectOutputStream οι οποίες υλοποιούν τις διεπαφές ObjectInput και ObjectOutput αντίστοιχα.

Βασική προϋπόθεση για το object streaming είναι να είναι οι κλάσεις Serializable (σειριοποιήσιμες).

Οι Βασικές μέθοδοι που χρησιμοποιούμε είναι:

Output Method

ObjectOutputStream ObjectOutputStream.writeObject

Input Method

ObjectInputStream ObjectInputStream.readObject

Στο παρακάτω παράδειγμα φαίνεται η γραφή και ανάγνωση αντικειμένων.

import java.io.*;
import java.math.BigDecimal;
import java.util.Calendar;
 
public class ObjectStreams {
    
    static final String dataFile = "timologio.dat";
    static final BigDecimal[] prices = { 
        new BigDecimal("19.99"), 
        new BigDecimal("9.99"),
        new BigDecimal("15.99"),
        new BigDecimal("3.99"),
        new BigDecimal("4.99") };
    static final int[] units = { 12, 8, 13, 29, 50 };
    static final String[] descs = { "Java T-shirt",
            "Java Mug",
            "Duke Juggling Dolls",
            "Java Pin",
            "Java Key Chain" };
 
    public static void main(String[] args) 
        throws IOException, ClassNotFoundException {
 
        ObjectOutputStream out = null;
        try {
            out = new ObjectOutputStream(new
                    BufferedOutputStream(new FileOutputStream(dataFile)));
 
            out.writeObject(Calendar.getInstance());
            for (int i = 0; i < prices.length; i ++) {
                out.writeObject(prices[i]);
                out.writeInt(units[i]);
                out.writeUTF(descs[i]);
            }
        } finally {
            out.close();
        }
 
        ObjectInputStream in = null;
        try {
            in = new ObjectInputStream(new
                    BufferedInputStream(new FileInputStream(dataFile)));
 
            Calendar date = null;
            BigDecimal price;
            int unit;
            String desc;
            BigDecimal total = new BigDecimal(0);
 
            date = (Calendar) in.readObject();
 
            System.out.format ("On %tA, %<tB %<te, %<tY:%n", date);
 
            try {
                while (true) {
                    price = (BigDecimal) in.readObject();
                    unit = in.readInt();
                    desc = in.readUTF();
                    System.out.format("You ordered %d units of %s at $%.2f%n",
                            unit, desc, price);
                    total = total.add(price.multiply(new BigDecimal(unit)));
                }
            } catch (EOFException e) {}
            System.out.format("For a TOTAL of: $%.2f%n", total);
        } finally {
            in.close();
        }
    }
}