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