| Both sides previous revision
Previous revision
Next revision
|
Previous revision
|
java:character_streams [2020/03/09 07:59] gthanos [Διαβάζοντας και γράφοντας γραμμή-γραμμή σε αρχείο κειμένου] |
java:character_streams [2021/04/04 16:20] |
| ====== Ροές Χαρακτήρων (Character Streams) ====== | |
| |
| Η Java χρησιμοποιεί για την κωδικοποίηση χαρακτήρων τη μορφοποίηση [[https://en.wikipedia.org/wiki/UTF-16|UTF-16]]. Το πρότυπο UTF-16 κωδικοποιεί κάθε χαρακτήρα σε 2 bytes (max 65000 χαρακτήρες), ενώ μπορεί να κωδικοποιήσει χαρακτήρες και σε 4 bytes, εάν οι συνδυασμοί των 65000 χαρακτήρων αποδειχθούν μη επαρκείς. | |
| |
| ==== Χρησιμοποιώντας Streams Xαρακτήρων ==== | |
| |
| Όλες οι κλάσεις που περιγράφουν stream χαρακτήρων κατάγονται από τις κλάσεις [[https://docs.oracle.com/javase/7/docs/api/java/io/Reader.html|Reader]] και [[https://docs.oracle.com/javase/7/docs/api/java/io/Writer.html|Writer]]. Σε αναλογία και με τα byte streams που είδαμε προηγούμενα, υπάρχουν οι κλάσεις [[https://docs.oracle.com/javase/7/docs/api/java/io/FileReader.html|FileReader]] και [[https://docs.oracle.com/javase/7/docs/api/java/io/FileWriter.html|FileWriter]] που επιτρέπουν την ανάγνωση και τη μορφοποιημένη εγγραφή streams χαρακτήρων από/σε αρχείο. Το παρακάτω παράδειγμα της κλάσης //CopyCharacters// παρουσιάζει τις κλάσεις αυτές. | |
| |
| <code java CopyCharacters.java> | |
| import java.io.FileReader; | |
| import java.io.FileWriter; | |
| import java.io.IOException; | |
| |
| public class CopyCharacters { | |
| public static void main(String[] args) throws IOException { | |
| |
| String filename; | |
| if(args.length > 0) | |
| filename = args[0]; | |
| else | |
| filename = "xanadu.txt"; | |
| | |
| try(FileReader reader = new FileReader(filename); | |
| FileWriter writer = new FileWriter("__"+filename) | |
| ) { | |
| int c; | |
| while ((c = reader.read()) != -1) { | |
| writer.write(c); | |
| } | |
| } | |
| } | |
| } | |
| </code> | |
| |
| Η κλάση //CopyCharacters// είναι παρόμοια με την κλάση //CopyBytes//. Η διαφορά είναι ότι η //CopyCharacters// χρησιμοποιεί τις κλάσεις [[https://docs.oracle.com/javase/7/docs/api/java/io/Reader.html και [[https://docs.oracle.com/javase/7/docs/api/java/io/Writer.html|FileWriter]] για είσοδο και έξοδο στη θέση των FileInputStream και FileOutputStream. Παρατηρήστε ότι τόσο η κλάση //CopyBytes// όσο και η κλάση //CopyCharacters// χρησιμοποιούν μια μεταβλητή int για να διαβάσουν και να γράψουν. Ωστόσο, στο //CopyCharacters//, η μεταβλητή int κρατά μια τιμή τύπου χαρακτήρα στα 16 τελευταία bit του ακεραίου, ενώ στο CopyBytes, η μεταβλητή int κρατά μια τιμή byte στα τελευταία 8 bit του ακεραίου. | |
| |
| ===== Διαβάζοντας και γράφοντας γραμμή-γραμμή σε αρχείο κειμένου ===== | |
| |
| Παραπάνω είδαμε την ανάγνωση και εγγραφή ενός χαρακτήρα σε κάθε κλήση των μεθόδων read και write. Προκειμένου να διαχειριζόμαστε περισσότερους χαρακτήρες σε κάθε κλήση των read και write, επιλέγουμε να διαβάζουμε και να γράφουμε ομάδες χαρακτήρων. | |
| |
| Μια συνηθισμένη ομαδοποίηση χαρακτήρων είναι γραμμή-γραμμή. Η γραμμή ορίζεται ως μία σειρά από χαρακτήρες με ένα χαρακτήρα αλλαγής γραμμής στο τέλος. Ο χαρακτήρας αλλαγής γραμμής μπορεί να είναι μια ακολουθία χαρακτήρων carriege return/line feed ('\r''\n') για το λειτουργικό σύστημα Windows, ένας χαρακτήρας carriege return ('\r'), ή ένας χαρακτήρας line feed ('\n') για το λειτουργικό σύστημα GNU/Linux. | |
| |
| Ας τροποποιήσουμε το παράδειγμα //CopyCharacters// για να χρησιμοποιήσουμε I/O χαρακτήρων για να διαβάσουμε και να γράψουμε γραμμή-γραμμή. Για να το κάνουμε αυτό, θα πρέπει να χρησιμοποιήσουμε δύο κλάσεις που δεν έχουμε ξαναδεί, τις [[https://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html|BufferedReader]] και [[https://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html|PrintWriter]]. | |
| |
| Το παράδειγμα [[CopyLines]] επικαλείται τις [[http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#readLine()|BufferedReader.readLine]] και [[http://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html#println()|PrintWriter.println]] για να διαβάσει και να γράψει μία γραμμή αντιστοίχως. | |
| |
| <code java CopyLines.java> | |
| import java.io.*; | |
| |
| public class CopyLines { | |
| public static void main(String[] args) throws IOException { | |
| | |
| String filename; | |
| if(args.length > 0) | |
| filename = args[0]; | |
| else | |
| filename = "xanadu.txt"; | |
| |
| try (BufferedReader reader = new BufferedReader(new FileReader(filename)); | |
| PrintWriter writer = new PrintWriter(new FileWriter("__"+filename)) | |
| ) { | |
| |
| String line; | |
| while ((line = reader.readLine()) != null) { | |
| writer.println(line); | |
| } | |
| } | |
| } | |
| } | |
| </code> | |
| |
| <WRAP tip 80% center round> | |
| Η κλήση της //readline// επιστρέφει μια γραμμή κειμένου χωρίς τον χαρακτήρα αλλαγής γραμμής στο τέλος. Η κλάση //CopyLines// εξάγει κάθε γραμμή και την ξαναγράφει χρησιμοποιώντας την //println//, η οποία προσθέτει στο τέλος τον χαρακτήρα αλλαγής γραμμής ο οποίος απαλήφθηκε κατά την ανάγνωση. | |
| </WRAP> | |
| |
| |Προηγούμενο: [[:java:byte_streams | Ροές Δεδομένων ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[java:util_scanner_class | Η κλάση Scanner ]]| | |