This is an old revision of the document!
Ο προηγούμενος κώδικας δουλεύει εξαιρετικά με ροές από bytes, στην πραγματικότητα όμως τα δεδομένα που θέλουμε να αποθηκεύσουμε ή να διαβάσουμε μπορεί να είναι ακέραιοι, αριθμοί κινητής υποδιαστολής κλπ. Προκειμένου να μπορέσουμε να διαβάσουμε ή να γράψουμε μορφές πληροφορίας που απαιτούν περισσότερα του ενός bytes έρχεται σε βοήθεια η κλάση java.nio.ByteBuffer. Η κλάση αυτή παρέχει ένα buffer μέσω του οποίου μπορούμε να γράψουμε ή να διαβάσουμε σύνθετους τύπους πληροφορίας.
Για παράδειγμα, ας υποθέσουμε ότι έχουμε μία σειρά από δεδομένα που θέλουμε να γράψουμε με συγκεκριμένη σειρά σε ένα αρχείο, όλα σε δυαδική μορφή. Προκειμένου να το επιτύχουμε θα πρέπει να κάνουμε τα εξής:
Η διαδικασία ανάγνωσης είναι ακριβώς η αντίστροφή, δηλαδή:
Το παρακάτω πρόγραμμα καλεί αρχικά τη συνάρτηση write η οποία αποθηκεύει έναν ακέραιο, ένα double, ένα χαρακτήρα (τον ελληνικό χαρακτρήρα 'Θ' (κεφαλαίο) και ένα string (το αλφαριθμητικό “Πως είσαι;”) σε ένα αρχείο με όνομα my.bin. Στη συνέχεια, το πρόγραμμα καλεί τη συνάρτηση read η οποια ανοίγει ένα FileInputStream για διάβασμα από το συγκεκριμένο αρχείο αποθηκεύει την πληροφορία που διάβασε σε ένα byte array από αυτό δημιουργεί ένα java.nio.ByteBuffer. Το buffer αυτό το χρησιμοποιούμε για να διαβάσουμε τα στοιχεία που αποθηκεύσαμε στο αρχείο με τη σειρά που τα βάλαμε.
import java.nio.*; import java.io.*; public class ByteBufferReadWriteTest { /* this method is only for debugging. * Comment out code, where method is called. */ public static void print_array(byte[] array) { int i=0; for(byte b: array) { System.out.format("%x", b); if(++i % 2 == 0) System.out.print(" "); } System.out.println(); } public static void main(String []args ) { File file = new File("my.bin"); write(file); read(file); } public static void write(File file) { int a = -159954; double b = 125.128953; char c = 'Θ'; String str = "Πώς είσαι;"; ByteBuffer buffer = ByteBuffer.allocate(34); buffer.putInt(a); buffer.putDouble(b); buffer.putChar(c); buffer.put(str.getBytes(java.nio.charset.StandardCharsets.UTF_8)); try(FileOutputStream out = new FileOutputStream(file)) { byte []array = buffer.array(); out.write(array); // just for debugging purposes // print_array(array); } catch(IOException ex) { System.out.println("Cannot write to file: "+file.getName()); } } public static void read(File file) { int a; double b; double c; byte array[] = new byte[512]; try(FileInputStream in = new FileInputStream(file)) { in.read(array); } catch(IOException ex) { System.out.println("Cannot read from file: "+file.getName()); } // just for debugging purposes // print_array(array); ByteBuffer buffer = ByteBuffer.wrap(array); System.out.println(buffer.getInt()); System.out.println(buffer.getDouble()); System.out.println(buffer.getChar()); byte [] str = new byte[18]; buffer.get(str); System.out.println(new String(str, java.nio.charset.StandardCharsets.UTF_8)); } }
H default υλοποίηση ενός ByteBuffer καταχωρεί τα δεδομένα ή διαβάζει τα δεδομένα κατά big-endian. Εάν θέλετε να αλλάξετε τη σειρά καταχώρησης των δεδομένων στο buffer σε little-endian, μπορείτε να χρησιμοποιήσετε τη μέθοδο order. H μέθοδος λαμβάνει ένα αντικείμενο της κλάσης java.nio.ByteOrder, το οποίο είναι ένα εκ των BIG_ENDIAN ή LITTLE_ENDIAN. Περισσότερες πληροφορίες για τις διαφορές μεταξύ big-endian και little-endian μπορείτε να βρείτε στο βίντεο.
read και προσπαθήστε να διαβάσετε από το buffer που μόλις γράψατε μέσα στη μέθοδο write. (βοήθεια: θα χρειαστείτε τη μέθοδο rewind της γονικής κλάσης java.nio.Buffer.Στις περιπτώσεις που τα δεδομένα γνωρίζουμε ότι έχουν αποθηκευτεί κατά big-endian εναλλακτικά της χρήσης των παραπάνω κλάσεων μπορούμε να χρησιμοποιήσουμε τις απλούστερες κλάσεις https://docs.oracle.com/javase/8/docs/api/java/io/DataInputStream.html και DataOutputStreamhttps://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html.