Προγραμματισμός

Java 101: Τα πλεονεκτήματα της τυπικής εισόδου / εξόδου

Στο προηγούμενο Java 101 άρθρα, αναφέρθηκα στις έννοιες της ανακατεύθυνσης, της τυπικής συσκευής εισόδου και της τυπικής συσκευής εξόδου. Για να αποδείξετε την εισαγωγή δεδομένων, κάλεσε αρκετά παραδείγματα System.in.read (). Τελικά φαίνεται πως System.in.read () εισάγει δεδομένα από την τυπική συσκευή εισόδου. Για να δείξετε δεδομένα εξόδου, ονομάζονται παραδείγματα System.out.print () και System.out.println (). Σε αντίθεση με System.in.read (), αυτά μεθόδους - ονόματα ακολουθιών εκτελέσιμου κώδικα (θα εξερευνηθούν στο άρθρο του επόμενου μήνα) - αποστολή της εξόδου τους στην τυπική συσκευή εξόδου Θέλετε να μάθετε περισσότερα σχετικά με τις τυπικές έννοιες εισόδου / εξόδου; Συνέχισε να διαβάζεις!

Πρότυπο I / O είναι ένας τυποποιημένος μηχανισμός εισόδου / εξόδου που προέρχεται από το λειτουργικό σύστημα Unix. Αν και αυτός ο μηχανισμός χρησιμοποιείται κυρίως με παλαιότερα λειτουργικά συστήματα εκτός GUI, το τυπικό I / O εξακολουθεί να παίζει ρόλο στα σύγχρονα λειτουργικά συστήματα GUI (γραφική διεπαφή χρήστη), όπου οι χρήστες το χρησιμοποιούν για να εντοπίσουν σφάλματα προγραμμάτων που δεν λειτουργούν και για να διδάξουν είσοδο / έξοδο στην είσοδο μαθήματα προγραμματισμού επιπέδου.

Όπως πιθανότατα μαντέψατε, το τυπικό I / O χρησιμοποιεί συσκευές για την εισαγωγή και την εξαγωγή δεδομένων. Αυτές οι συσκευές περιλαμβάνουν τυπική είσοδο, τυπική έξοδο και τυπικό σφάλμα.

Τυπική είσοδος

ο τυπική συσκευή εισόδου είναι εκείνο το τμήμα του λειτουργικού συστήματος που ελέγχει από το σημείο όπου ένα πρόγραμμα λαμβάνει την είσοδό του. Από προεπιλογή, η τυπική συσκευή εισόδου διαβάζει αυτήν την είσοδο από ένα πρόγραμμα οδήγησης συσκευής που είναι συνδεδεμένο στο πληκτρολόγιο. Ωστόσο, μπορείτε διευθύνω πάλιν, ή εναλλαγή, η πηγή εισόδου σε ένα πρόγραμμα οδήγησης συσκευής που είναι συνδεδεμένο σε ένα αρχείο έτσι ώστε η είσοδος να φαίνεται "μαγικά" που προέρχεται από ένα αρχείο - αντί για το πληκτρολόγιο.

Ένα πρόγραμμα εισάγει τα δεδομένα του από την τυπική συσκευή εισόδου καλώντας Java System.in.read () μέθοδος. Κοιτάξτε στην τεκμηρίωση SDK και θα ανακαλύψετε μια τάξη που ονομάζεται Σύστημα. Αυτή η τάξη περιέχει μια μεταβλητή που ονομάζεται σε - ένα αντικείμενο που δημιουργήθηκε από μια υποκατηγορία του InputStream. Ο χαρακτήρας περιόδου μετά Σύστημα δηλώνει ότι σε ανήκει στον Σύστημα, και ο χαρακτήρας περιόδου μετά σε δηλώνει ότι ανάγνωση() ανήκει στον σε. Με άλλα λόγια, ανάγνωση() είναι μια μέθοδος που ανήκει σε ένα αντικείμενο που ονομάζεται σε, το οποίο με τη σειρά του ανήκει σε μια τάξη που ονομάζεται Σύστημα. (Θα συζητήσω περισσότερα για μαθήματα, αντικείμενα και "ανήκουν" στον επόμενο μήνα.)

System.in.read () δεν παίρνει επιχειρήματα και επιστρέφει έναν ακέραιο, γεγονός που οδήγησε ορισμένους να το πιστέψουν System.in.read () επιστρέφει ακέραιους αριθμούς που έχουν εισαχθεί από τον χρήστη. Να ξεκαθαρίσω, System.in.read () είτε επιστρέφει τον κωδικό ASCII 7-bit ενός κλειδιού (εάν η τυπική συσκευή εισόδου έχει ρυθμιστεί στο πληκτρολόγιο) είτε ένα byte 8-bit από ένα αρχείο (εάν η τυπική συσκευή εισόδου έχει ανακατευθυνθεί από το πληκτρολόγιο σε ένα αρχείο). Σε άλλη περίπτωση, System.in.read () μετατρέπει τον κώδικα σε ακέραιο αριθμό 32-bit και επιστρέφει το αποτέλεσμα.

Ας υποθέσουμε ότι η τυπική συσκευή εισόδου έχει ρυθμιστεί στο πληκτρολόγιο. Το παρακάτω είναι μια περιγραφή του τι συμβαίνει στα Windows: Όταν πληκτρολογείτε ένα κλειδί σε ένα πληκτρολόγιο που ελέγχεται από Windows, το λειτουργικό σύστημα αποθηκεύει τον κωδικό ASCII 7-bit αυτού του κλειδιού σε ένα εσωτερικό buffer κλειδιού. Αυτό το buffer διαθέτει έως και περίπου 16 κωδικούς ASCII και οργανώνεται ως δομή δεδομένων κυκλικής ουράς πρώτης / πρώτης εξόδου. System.in.read () ανακτά τον κωδικό ASCII από την κεφαλή του buffer κλειδιών και στη συνέχεια αφαιρεί αυτόν τον κωδικό από το buffer κλειδιών. Αυτός ο κωδικός 7-bit ASCII μετατρέπεται σε int -- με System.in.read () Προετοιμασία 25 μηδέν bit στον κώδικα - και επιστρέφει στον καλούντα της μεθόδου. Ενα δεύτερο System.in.read () η μέθοδος κλήσης ανακτά τον επόμενο κωδικό ASCII, ο οποίος βρίσκεται τώρα στην κορυφή του buffer κλειδιών και ούτω καθεξής.

Ας υποθέσουμε ότι δεν υπάρχουν κωδικοί ASCII στο buffer κλειδιών. Τι συμβαίνει; System.in.read () περιμένει ο χρήστης να πληκτρολογήσει πλήκτρα και να πατήσει το τερματικό. Στα Windows, αυτός ο τερματιστής είναι το Εισαγω κλειδί. Πάτημα Εισαγω προκαλεί τα Windows να αποθηκεύουν έναν κωδικό επιστροφής μεταφοράς (ASCII 13) ακολουθούμενο από έναν κωδικό νέας γραμμής (ASCII 10) στο buffer κλειδιών. Επομένως, το buffer κλειδιού ενδέχεται να περιέχει πολλούς κωδικούς ASCII ακολουθούμενο από επιστροφή μεταφοράς και χαρακτήρα νέας γραμμής. Ο πρώτος από αυτούς τους κωδικούς επιστρέφει από System.in.read (). Ελέγξτε αυτήν τη δραστηριότητα πληκτρολογώντας, μεταγλώττισης και εκτελώντας το Ηχώ εφαρμογή; Ο πηγαίος κώδικας του εμφανίζεται στην Καταχώριση 1.

Λίστα 1. Echo.java

// Echo.java class Echo {public static void main (String [] args) ρίχνει το java.io.IOException {int ch; System.out.print ("Εισαγάγετε κάποιο κείμενο:"); ενώ ((ch = System.in.read ())! = '\ n') System.out.print ((char) ch); }} 

Ηχώ ολοκληρώνει τα ακόλουθα βήματα:

  1. Καλεί το System.out.print () μέθοδος, η οποία παίρνει ένα Σειρά όρισμα, για την έξοδο μιας προτροπής
  2. Κλήσεις System.in.read () για την εισαγωγή κωδικών ASCII από την τυπική συσκευή εισόδου ως ακέραιοι 32-bit
  3. Μετατρέπει αυτούς τους ακέραιους 32-bit σε χαρακτήρες Unicode 16-bit μέσω του (απανθρακώνω) εκμαγείο
  4. Καλεί το System.out.print () μέθοδος, η οποία παίρνει ένα απανθρακώνω επιχείρημα, για να επαναλάβετε αυτούς τους χαρακτήρες Unicode στην τυπική συσκευή εξόδου

Τα τελευταία τρία βήματα στα προηγούμενα τέσσερα βήματα πραγματοποιούνται σε ένα βρόχο λίγο και συνεχίζονται μέχρι να διαβαστεί ένας χαρακτήρας νέας γραμμής. Τρέχω Ηχώ έτσι ώστε να εισέρχεται από το πληκτρολόγιο και να εξέρχεται στην οθόνη, εκδώστε την ακόλουθη γραμμή εντολών: java Echo.

Παρόλο System.in.read () δεν ρίχνει ποτέ εξαίρεση (ανατρέξτε στο θέμα καταμέτρησης λέξεων σε αυτό το άρθρο για ορισμό αυτού του όρου), όταν η τυπική συσκευή εισόδου έχει οριστεί στο πληκτρολόγιο, ενδέχεται να ρίξει μια εξαίρεση όταν ανακατευθύνετε την τυπική συσκευή εισόδου από το πληκτρολόγιο αρχείο. Για παράδειγμα, ας υποθέσουμε ότι ανακατευθύνετε την τυπική συσκευή εισόδου σε ένα αρχείο και System.in.read () διαβάζει περιεχόμενο από το αρχείο. Ας υποθέσουμε τώρα ότι το αρχείο βρίσκεται σε μια δισκέτα και ο χρήστης εξαγάγει αυτόν τον δίσκο κατά τη λειτουργία ανάγνωσης. Όταν πραγματοποιηθεί η εκτόξευση, System.in.read () ρίχνει μια εξαίρεση, ενημερώνοντας το πρόγραμμα ότι δεν μπορεί να διαβάσει το αρχείο. Αυτό παρέχει τον λόγο προσάρτησης του ρίχνει το java.io.IOException ρήτρα προς το κύριος() κεφαλίδα μεθόδου. (Θα μελετήσετε εξαιρέσεις, εξαιρέσεις και συναφείς έννοιες σε μελλοντικό άρθρο.)

Πώς ανακατευθύνετε την τυπική συσκευή εισόδου έτσι ώστε η είσοδος να προέρχεται από ένα αρχείο; Η απάντηση είναι να εισαγάγετε ένα λιγότερο από το σύμβολο, <, στη γραμμή εντολών και ακολουθήστε αυτό το σύμβολο με όνομα αρχείου. Για να δείτε πώς λειτουργεί, εκδώστε την ακόλουθη γραμμή εντολών: java Echo <>. Η γραμμή εντολών ανακατευθύνει την τυπική συσκευή εισόδου σε ένα αρχείο που ονομάζεται Echo.java. Πότε Ηχώ εκτελείται, επειδή κάθε γραμμή καταλήγει σε χαρακτήρα νέας γραμμής, μόνο στην πρώτη γραμμή κειμένου Echo.java εμφανίζεται στην οθόνη.

Ας υποθέσουμε ότι χρειάζεστε ένα βοηθητικό πρόγραμμα που διαβάζει ένα ολόκληρο αρχείο και είτε εμφανίζει τα περιεχόμενα του αρχείου στην οθόνη, αντιγράφει αυτά τα περιεχόμενα σε άλλο αρχείο ή αντιγράφει αυτά τα περιεχόμενα σε έναν εκτυπωτή. Δυστυχώς, το Ηχώ Το πρόγραμμα εκτελεί αυτήν την εργασία μόνο μέχρι να συναντήσει τον πρώτο χαρακτήρα νέας γραμμής. Τι κάνεις? Η απάντηση στο πρόβλημα βρίσκεται στο Τύπος εφαρμογή. Η λίστα 2 παρέχει τον πηγαίο κώδικα:

Λίστα 2. Type.java

// Type.java class Type {public static void main (String [] args) ρίχνει το java.io.IOException {int ch; ενώ ((ch = System.in.read ())! = -1) System.out.print ((char) ch); }} 

Τύπος μοιάζει με Ηχώ, ωστόσο, δεν υπάρχει προτροπή, και η δοκιμή loop loop ενάντια -1 (που δείχνει το τέλος του αρχείου) αντί για \ n (που δείχνει το τέλος της γραμμής). Τρέχω Τύπος, εκδώστε την ακόλουθη γραμμή εντολών: Τύπος java <>. Το περιεχόμενο του Πληκτρολογήστε java - ή όποιο αρχείο έχει καθοριστεί - θα εμφανιστεί. Ως πείραμα, δοκιμάστε να προσδιορίσετε Τύπος java. Τι νομίζετε ότι θα συμβεί; (Συμβουλή: αυτό το πρόγραμμα μοιάζει Ηχώ αλλά δεν τελειώνει μέχρι να πατήσετε Ctrl + C.)

Νωρίτερα, ανέφερα ότι μερικοί προγραμματιστές το πιστεύουν λανθασμένα System.in.read () επιστρέφει έναν αριθμό που έχει εισαχθεί από τον χρήστη. Όπως μόλις είδατε, αυτό δεν ισχύει. Αλλά τι πρέπει να κάνετε αν θέλετε να χρησιμοποιήσετε System.in.read () να ανακτήσετε έναν αριθμό; Ρίξτε μια ματιά στο Μετατρέπω εφαρμογή, του οποίου ο πηγαίος κώδικας εμφανίζεται στην καταχώριση 3.

Λίστα 3. Convert.java

// Convert.java class Μετατροπή {public static void main (String [] args) ρίχνει java.io.IOException {System.out.print ("Παρακαλώ εισάγετε έναν αριθμό:"); int num = 0; int ch; ενώ ((ch = System.in.read ())! = '\ n') εάν (ch> = '0' && ch <= '9') {num * = 10; αριθμός + = ch - '0'; } άλλο διάλειμμα System.out.println ("num =" + num); System.out.println ("num squared =" + num * num); }} 

Λίστα 3's Μετατρέπω Το πρόγραμμα ζητά από το χρήστη να εισαγάγει έναν αριθμό (μέσω System.out.print ("Παρακαλώ εισάγετε έναν αριθμό:");). Διαβάζει αυτά τα ψηφία - ένα κάθε φορά - και μετατρέπει τον αριθμητικό κωδικό κάθε ψηφίου σε δυαδικό αριθμό που προστίθεται σε μια μεταβλητή που ονομάζεται αριθ. Τέλος, καλεί σε System.out.println () εξάγετε την τιμή μέσα αριθ και το τετράγωνο αυτής της τιμής στην τυπική συσκευή εξόδου.

Μετατρέπω επιδεικνύει την τεχνική που χρησιμοποιεί το χρόνο για να χρησιμοποιήσει ένα βρόχο λίγο για να δοκιμάσει ένα ψηφίο, να προ-πολλαπλασιάσει μια μεταβλητή κατά 10 (για να κάνει χώρο για το εισερχόμενο ψηφίο), μετατρέποντας ένα ψηφίο στο δυαδικό ισοδύναμό του και προσθέτοντας αυτό το δυαδικό ισοδύναμο με τη μεταβλητή. Ωστόσο, αυτή η τεχνική δεν είναι μια σωστή τεχνική για χρήση εάν γράφετε ένα πρόγραμμα για ανάπτυξη σε διαφορετικές χώρες καθώς ορισμένες χώρες χρησιμοποιούν ψηφία διαφορετικά από 0 έως 9 - όπως τα ψηφία Ταμίλ. Για να κάνετε το πρόγραμμα να λειτουργεί με άλλα ψηφία, πρέπει να επεκτείνετε τη δήλωση if για να ελέγξετε αυτά τα ψηφία και να τροποποιήσετε το ch - «0» έκφραση. Ευτυχώς, η Java απλοποιεί αυτήν την εργασία παρέχοντας ένα Χαρακτήρας τάξη, την οποία θα εξερευνήσετε σε μελλοντικό άρθρο.

Τυπική έξοδος

ο τυπική συσκευή εξόδου είναι το μέρος του λειτουργικού συστήματος που ελέγχει πού στέλνει ένα πρόγραμμα το αποτέλεσμα. Από προεπιλογή, η τυπική συσκευή εξόδου στέλνει την έξοδο σε ένα πρόγραμμα οδήγησης συσκευής που είναι προσαρτημένο στην οθόνη. Ωστόσο, ο προορισμός εξόδου μπορεί να ανακατευθυνθεί σε ένα πρόγραμμα οδήγησης συσκευής που είναι συνδεδεμένο σε ένα αρχείο ή έναν εκτυπωτή, με αποτέλεσμα το ίδιο πρόγραμμα να εμφανίζει τα ευρήματά του στην οθόνη, να τα αποθηκεύει σε ένα αρχείο ή να παρέχει μια έντυπη λίστα των αποτελεσμάτων.

Επιτυγχάνετε τυπική έξοδο καλώντας Java System.out.print () και System.out.println () μεθόδους. Εκτός από το γεγονός ότι Τυπώνω() Οι μέθοδοι δεν παράγουν χαρακτήρα νέας γραμμής μετά τα δεδομένα, οι δύο ομάδες μεθόδων είναι ισοδύναμες. Υπάρχουν μέθοδοι για την έξοδο Boolean, χαρακτήρα, πίνακας χαρακτήρων, κινούμενου σημείου διπλής ακρίβειας, κινούμενου σημείου, ακέραιου, μεγάλου ακέραιου, συμβολοσειράς και τιμών αντικειμένου. Για να δείξετε αυτές τις μεθόδους, η Λίστα 4 παρουσιάζει τον πηγαίο κώδικα στο Τυπώνω εφαρμογή.

Λίστα 4. Print.java

// Print.java class Εκτύπωση {public static void main (String [] args) {boolean b = true; System.out.println (b); char c = «Α»; System.out.println (γ); char [] carray = {'A', 'B', 'C'}; System.out.println (carray); διπλό d = 3,5; System.out.println (δ); float f = -9.3f; System.out.println (στ); int i = "Χ"; System.out.println (i); μακρύ l = 9000000; System.out.println (l); Συμβολοσειρά s = "abc"; System.out.println (s); System.out.println (νέα εκτύπωση ()); }} 

Η καταχώριση 4 προκάλεσε πιθανώς κάποιες ερωτήσεις για εσάς. Πρώτον, τι είναι όλα αυτά System.out. επιχείρηση που κάνει μπροστά εκτύπωση (); Και πάλι, ανατρέξτε στο Σύστημα τάξη στην τεκμηρίωση SDK. Η τάξη περιέχει μια μεταβλητή που ονομάζεται έξω - ένα αντικείμενο που δημιουργήθηκε από μια κλάση που ονομάζεται PrintStream. Ο χαρακτήρας περιόδου μετά Σύστημα δείχνει ότι έξω ανήκει στον Σύστημα. Ο χαρακτήρας της περιόδου μετά έξω δηλώνει ότι εκτύπωση () ανήκει στον έξω. Με άλλα λόγια, εκτύπωση () είναι μια μέθοδος που ανήκει σε ένα αντικείμενο που ονομάζεται έξω, το οποίο με τη σειρά του ανήκει σε μια τάξη που ονομάζεται Σύστημα.

Η δεύτερη ερώτηση που μπορεί να κάνετε στον εαυτό σας περιλαμβάνει εκτύπωση () τύποι δεδομένων ορίσματος: πώς είναι δυνατόν για το ίδιο εκτύπωση () μέθοδος που καλείται με διαφορετικούς τύπους δεδομένων επιχειρημάτων; Η απάντηση: γιατί υπάρχουν πολλά εκτύπωση () μεθόδους στο PrintStream τάξη. Κατά το χρόνο εκτέλεσης, το JVM ξέρει ποιο εκτύπωση () μέθοδος κλήσης εξετάζοντας τον αριθμό των ορισμάτων μεθόδου-κλήσης και τους τύπους δεδομένων τους. (Η δήλωση πολλών μεθόδων με το ίδιο όνομα αλλά διαφορετικοί αριθμοί επιχειρημάτων και τύπων δεδομένων επιχειρήματος είναι γνωστός ως μέθοδος υπερφόρτωσης. Θα συζητήσω αυτήν την ιδέα τον επόμενο μήνα.)

Τέλος, μπορεί να αναρωτιέστε System.out.println (νέα εκτύπωση ());. Αυτή η μέθοδος κλήσης απεικονίζει το εκτύπωση () μέθοδος, η οποία παίρνει ένα Αντικείμενο διαφωνία. Πρώτον, ο τελεστής δημιουργίας νέος δημιουργεί ένα αντικείμενο από το Τυπώνω class και επιστρέφει μια αναφορά σε - επίσης γνωστή ως διεύθυνση - αυτού του αντικειμένου. Τέλος, αυτή η διεύθυνση περνά ως επιχείρημα στο εκτύπωση () μέθοδος, η οποία παίρνει ένα Αντικείμενο διαφωνία. Η μέθοδος μετατρέπει τα περιεχόμενα του αντικειμένου σε μια συμβολοσειρά και εξάγει αυτήν τη συμβολοσειρά. Από προεπιλογή, η συμβολοσειρά αποτελείται από το όνομα της κλάσης του αντικειμένου, ακολουθούμενο από ένα @ χαρακτήρας (at), ακολουθούμενος από έναν δεκαεξαδικό ακέραιο μορφότυπο που αντιπροσωπεύει τον κωδικό πρόσβασης του αντικειμένου. (Θα παρουσιάσω κωδικούς hash και τη μετατροπή αντικειμένων σε συμβολοσειρές σε ένα επερχόμενο άρθρο.)

Συντάσσω Print.java και εκτελέστε το πρόγραμμα εκδίδοντας την ακόλουθη γραμμή εντολών: java Εκτύπωση. Θα πρέπει να δείτε εννέα γραμμές εξόδου. Ανακατευθύνετε αυτήν την έξοδο στο έξω αρχείο εκδίδοντας την ακόλουθη γραμμή εντολών: java Εκτύπωση> out.dat. Τώρα μπορείτε να δείτε τα περιεχόμενα του αρχείου.

Το μεγαλύτερο από το σύμβολο, >, υποδεικνύει τυπική ανακατεύθυνση εξόδου. Όποτε θέλετε να ανακατευθύνετε την τυπική συσκευή εξόδου από την οθόνη σε ένα αρχείο ή εκτυπωτή, καθορίστε το σύμβολο που ακολουθείται από το όνομα του αρχείου ή του εκτυπωτή στη γραμμή εντολών. Για παράδειγμα, ανακατεύθυνση ΤυπώνωΈξοδος σε εκτυπωτή Windows εκδίδοντας την ακόλουθη γραμμή εντολών: java Εκτύπωση> prn.