| Both sides previous revision
Previous revision
Next revision
|
Previous revision
Next revision
Both sides next revision
|
java:byte_streams_to_data [2020/03/08 22:55] gthanos |
java:byte_streams_to_data [2021/04/04 16:42] gthanos [Μετασχηματισμός των ροών δυαδικών δεδομένων σε βασικούς τύπους δεδομένων] |
| ====== Μετασχηματισμός των ροών δεδομένων σε βασικούς τύπους δεδομένων ====== | ====== Μετασχηματισμός των ροών δυαδικών δεδομένων σε βασικούς τύπους δεδομένων ====== |
| |
| Ο προηγούμενος κώδικας δουλεύει εξαιρετικά με ροές από bytes, στην πραγματικότητα όμως τα δεδομένα που θέλουμε να αποθηκεύσουμε ή να διαβάσουμε μπορεί να είναι ακέραιοι, αριθμοί κινητής υποδιαστολής ή άλλοι βασικοί τύποι δεδομένων. Προκειμένου να μπορέσουμε να διαβάσουμε ή να γράψουμε μορφές πληροφορίας που απαιτούν περισσότερα του ενός bytes έρχεται σε βοήθεια η κλάση [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|java.nio.ByteBuffer]]. Η κλάση αυτή παρέχει ένα buffer μέσω του οποίου μπορούμε να γράψουμε ή να διαβάσουμε σύνθετους τύπους πληροφορίας. | Ο προηγούμενος κώδικας δουλεύει εξαιρετικά με ροές από bytes, στην πραγματικότητα όμως τα δεδομένα που θέλουμε να αποθηκεύσουμε ή να διαβάσουμε μπορεί να είναι ακέραιοι, αριθμοί κινητής υποδιαστολής ή άλλοι βασικοί τύποι δεδομένων. Προκειμένου να μπορέσουμε να διαβάσουμε ή να γράψουμε μορφές πληροφορίας που απαιτούν περισσότερα του ενός bytes έρχεται σε βοήθεια η κλάση [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|java.nio.ByteBuffer]]. Η κλάση αυτή παρέχει ένα buffer μέσω του οποίου μπορούμε να γράψουμε ή να διαβάσουμε σύνθετους τύπους πληροφορίας. |
| Η διαδικασία ανάγνωσης είναι ακριβώς η αντίστροφή, δηλαδή: | Η διαδικασία ανάγνωσης είναι ακριβώς η αντίστροφή, δηλαδή: |
| - διαβάζουμε από ένα [[https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html|InputStream]] την πληροφορία σε ένα πίνακα από bytes. | - διαβάζουμε από ένα [[https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html|InputStream]] την πληροφορία σε ένα πίνακα από bytes. |
| - Από τον πίνακα αυτό δημιουργούμε ένα [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|java.nio.ByteBuffer]]. | - από τον πίνακα αυτό δημιουργούμε ένα [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|java.nio.ByteBuffer]]. |
| - Από το [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|java.nio.ByteBuffer]] εξάγουμε την πληροφορία με τη σειρά που γνωρίζουμε ότι αυτή είναι αποθηκευμένη. | - από το [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|java.nio.ByteBuffer]] εξάγουμε την πληροφορία με τη σειρά που γνωρίζουμε ότι αυτή είναι αποθηκευμένη. |
| |
| Το παρακάτω πρόγραμμα καλεί αρχικά τη συνάρτηση ''write'' η οποία αποθηκεύει έναν ακέραιο, ένα double, ένα χαρακτήρα (τον ελληνικό χαρακτρήρα 'Θ' (κεφαλαίο) και ένα string (το αλφαριθμητικό "Πως είσαι;") σε ένα αρχείο με όνομα **my.bin**. Στη συνέχεια, το πρόγραμμα καλεί τη συνάρτηση ''read'' η οποια ανοίγει ένα [[https://docs.oracle.com/javase/8/docs/api/java/io/FileInputStream.html|FileInputStream]] για διάβασμα από το συγκεκριμένο αρχείο αποθηκεύει την πληροφορία που διάβασε σε ένα byte array από αυτό δημιουργεί ένα [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|java.nio.ByteBuffer]]. Το buffer αυτό το χρησιμοποιούμε για να διαβάσουμε τα στοιχεία που αποθηκεύσαμε στο αρχείο με τη σειρά που τα βάλαμε. | Το παρακάτω πρόγραμμα καλεί αρχικά τη συνάρτηση ''write'' η οποία χρησιμοποιεί ένα [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|java.nio.ByteBuffer]] για να αποθηκεύσει έναν ακέραιο, ένα double, ένα χαρακτήρα (τον ελληνικό χαρακτρήρα 'Θ' (κεφαλαίο) και ένα string (το αλφαριθμητικό "Πως είσαι;") σε ένα αρχείο με όνομα **my.bin**. Στη συνέχεια, το πρόγραμμα καλεί τη συνάρτηση ''read'' η οποια ανοίγει ένα [[https://docs.oracle.com/javase/8/docs/api/java/io/FileInputStream.html|FileInputStream]] για διάβασμα από το συγκεκριμένο αρχείο αποθηκεύει την πληροφορία που διάβασε σε ένα byte array από αυτό δημιουργεί ένα [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|java.nio.ByteBuffer]]. Το buffer αυτό το χρησιμοποιούμε για να διαβάσουμε τα στοιχεία που αποθηκεύσαμε στο αρχείο με τη σειρά που τα βάλαμε. |
| |
| <code java BufferReadWriteTest.java> | <code java ByteBufferReadWriteTest.java> |
| import java.nio.*; | import java.nio.*; |
| import java.io.*; | import java.io.*; |
| | import java.util.Arrays; |
| |
| public class ByteBufferReadWriteTest { | public class ByteBufferReadWriteTest { |
| | |
| public static void main(String []args ) { | public static void main(String []args ) { |
| File file = new File("my.bin"); | File file = new File("file.bin"); |
| write(file); | write(file); |
| read(file); | read(file); |
| int a = -159954; | int a = -159954; |
| double b = 125.128953; | double b = 125.128953; |
| char c = 'Θ'; | char c = 'θ'; |
| String str = "Πώς είσαι;"; | String str = "Πώς είσαι;"; |
| | |
| ByteBuffer buffer = ByteBuffer.allocate(34); | ByteBuffer buffer = ByteBuffer.allocate(512); |
| | buffer.order(ByteOrder.BIG_ENDIAN); |
| buffer.putInt(a); | buffer.putInt(a); |
| buffer.putDouble(b); | buffer.putDouble(b); |
| buffer.putChar(c); | buffer.putChar(c); |
| buffer.put(str.getBytes(java.nio.charset.StandardCharsets.UTF_8)); | buffer.put(str.getBytes(java.nio.charset.StandardCharsets.UTF_8)); |
| | int buffer_size = buffer.position(); |
| | |
| try(FileOutputStream out = new FileOutputStream(file)) { | try(FileOutputStream out = new FileOutputStream(file)) { |
| byte []array = buffer.array(); | byte []array = buffer.array(); |
| | array = Arrays.copyOf(array, buffer_size); |
| out.write(array); | out.write(array); |
| // just for debugging purposes | // just for debugging purposes |
| // print_array(array); | //print_array(array); |
| } | } |
| catch(IOException ex) { | catch(IOException ex) { |
| | |
| byte array[] = new byte[512]; | byte array[] = new byte[512]; |
| | int read_size; |
| try(FileInputStream in = new FileInputStream(file)) { | try(FileInputStream in = new FileInputStream(file)) { |
| in.read(array); | read_size = in.read(array); |
| | array = Arrays.copyOf(array, read_size); |
| } | } |
| catch(IOException ex) { | catch(IOException ex) { |
| } | } |
| // just for debugging purposes | // just for debugging purposes |
| // print_array(array); | //print_array(array); |
| | |
| ByteBuffer buffer = ByteBuffer.wrap(array); | ByteBuffer buffer = ByteBuffer.wrap(array); |
| | buffer.order(ByteOrder.BIG_ENDIAN); |
| System.out.println(buffer.getInt()); | System.out.println(buffer.getInt()); |
| System.out.println(buffer.getDouble()); | System.out.println(buffer.getDouble()); |
| System.out.println(buffer.getChar()); | System.out.println("'"+buffer.getChar()+"'"); |
| byte [] str = new byte[18]; | int str_size = buffer.remaining(); |
| buffer.get(str); | byte[] bytes = new byte[str_size]; |
| System.out.println(new String(str, java.nio.charset.StandardCharsets.UTF_8)); | buffer.get(bytes); |
| | System.out.println(new String(bytes, java.nio.charset.StandardCharsets.UTF_8)); |
| } | } |
| } | } |
| |
| <WRAP tip 80% center round> | <WRAP tip 80% center round> |
| H //default// υλοποίηση ενός [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|ByteBuffer]] καταχωρεί τα δεδομένα ή διαβάζει τα δεδομένα κατά big-endian. Εάν θέλετε να αλλάξετε τη σειρά καταχώρησης των δεδομένων στο buffer σε little-endian, μπορείτε να χρησιμοποιήσετε τη μέθοδο [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#order-java.nio.ByteOrder-|order]]. H μέθοδος λαμβάνει ένα αντικείμενο της κλάσης [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteOrder.html|java.nio.ByteOrder]], το οποίο είναι ένα εκ των **BIG_ENDIAN** ή **LITTLE_ENDIAN**. | H //default// υλοποίηση ενός [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html|ByteBuffer]] καταχωρεί τα δεδομένα ή διαβάζει τα δεδομένα κατά big-endian. Εάν θέλετε να αλλάξετε τη σειρά καταχώρησης των δεδομένων στο buffer σε little-endian, μπορείτε να χρησιμοποιήσετε τη μέθοδο [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#order-java.nio.ByteOrder-|order]]. H μέθοδος λαμβάνει ένα αντικείμενο της κλάσης [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteOrder.html|java.nio.ByteOrder]], το οποίο είναι ένα εκ των [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteOrder.html#BIG_ENDIAN|java.nio.ByteOrder.BIG_ENDIAN]] ή [[https://docs.oracle.com/javase/8/docs/api/java/nio/ByteOrder.html#LITTLE_ENDIAN|java.nio.ByteOrder.LITTLE_ENDIAN]]. |
| Περισσότερες πληροφορίες για τις διαφορές μεταξύ big-endian και little-endian μπορείτε να βρείτε [[https://www.youtube.com/watch?v=seZLUbgbB7Y|στο βίντεο]]. | Πληροφορίες για τη διαφορά μεταξύ big-endian και little-endian μπορείτε να βρείτε [[https://www.youtube.com/watch?v=seZLUbgbB7Y|στο βίντεο]]. |
| </WRAP> | </WRAP> |
| |
| <WRAP todo 80% center round> | <WRAP todo 80% center round> |
| - Αλλάξτε το παραπάνω παράδειγμα, ώστε τα δεδομένα να αποθηκεύονται κατά little-endian και όχι κατά big-endian που είναι το default. | - Αλλάξτε το παραπάνω παράδειγμα, ώστε τα δεδομένα να αποθηκεύονται κατά little-endian και όχι κατά big-endian που είναι το default. |
| - Βάλτε σε σχόλια τη στατική μέθοδο ''read'' και προσπαθήστε να διαβάσετε από το buffer που μόλις γράψατε μέσα στη μέθοδο ''write''. (βοήθεια: θα χρειαστείτε τη μέθοδο rewind της γονικής κλάσης [[https://docs.oracle.com/javase/8/docs/api/java/nio/Buffer.html|java.nio.Buffer]]. | - Βάλτε σε σχόλια τη στατική μέθοδο ''read'' και προσπαθήστε να διαβάσετε μέσα στη μέθοδο ''write'' από το buffer που μόλις γράψατε. (βοήθεια: θα χρειαστείτε τη μέθοδο //rewind// της γονικής κλάσης [[https://docs.oracle.com/javase/8/docs/api/java/nio/Buffer.html|java.nio.Buffer]]. |
| </WRAP> | </WRAP> |
| |
| |
| <WRAP tip 80% center round> | <WRAP tip 80% center round> |
| Η κλάσεις [[https://docs.oracle.com/javase/8/docs/api/java/io/DataInputStream.html|DataInputStream]] και [[https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html|DataOutputStream]] δεν δίνουν τη δυνατότητα να αλλάξετε το endianism των τύπων που αποθηκεύονται στο stream. | Η κλάσεις [[https://docs.oracle.com/javase/8/docs/api/java/io/DataInputStream.html|DataInputStream]] και [[https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html|DataOutputStream]] δεν δίνουν τη δυνατότητα να αλλάξετε το endianness των τύπων που αποθηκεύονται στο stream. |
| |
| </WRAP> | </WRAP> |
| Παρατηρήστε ότι και στις δύο περιπτώσεις μπορείτε να αλλάξετε την κωδικοποίηση των Strings που αποθηκεύονται μέσα στο stream. Στα παραπάνω παραδείγματα αλλάξτε την κωδικοποίηση σε UTF-8 από UTF-16. | Παρατηρήστε ότι και στις δύο περιπτώσεις μπορείτε να αλλάξετε την κωδικοποίηση των Strings που αποθηκεύονται μέσα στο stream. Στα παραπάνω παραδείγματα αλλάξτε την κωδικοποίηση σε UTF-8 από UTF-16. |
| </WRAP> | </WRAP> |
| | |
| | |Προηγούμενο: [[:java:byte_streams | Ροές δυαδικών δεδομένων ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[:java:character_streams | Ροές χαρακτήρων]] | |
| |