Java 101: Ulaz i izlaz standardnog ulaza / izlaza

U prethodnim člancima o Javi 101 pozivao sam se na koncepte preusmjeravanja, standardni ulazni uređaj i standardni izlazni uređaj. Za demonstraciju unosa podataka nazvano je nekoliko primjera System.in.read(). Ispada da System.in.read()podaci unose sa standardnog uređaja za unos. Da bi demonstrirali izlaz podataka, primjeri pozvani System.out.print()i System.out.println(). Za razliku od System.in.read()tih metoda - imenovane sekvence izvršnog koda (koje će se istražiti u članku sljedećeg mjeseca) - svoj izlaz šalju na standardni izlazni uređaj. Želite li znati više o standardnim I / O konceptima? Nastavi čitati!

Standardni I / O standardizirani je ulazno / izlazni mehanizam koji potječe iz operativnog sustava Unix. Iako se ovaj mehanizam uglavnom koristi sa starijim ne-GUI operativnim sustavima, standardni I / O i dalje igra ulogu u modernim GUI (grafičko korisničko sučelje) operativnim sustavima, gdje ga ljudi koriste za otklanjanje pogrešaka u programima i podučavanje ulaza / izlaza u ulaznom tečajevi programiranja na razini.

Kao što ste vjerojatno pretpostavili, standardni I / O koristi uređaje za unos i izlaz podataka. Ti uređaji uključuju standardni ulaz, standardni izlaz i standardnu ​​pogrešku.

Standardni ulaz

Standardni unos je dio operacijskog sustava koji kontrolira odakle program dobiva svoj ulaz. Prema zadanim postavkama standardni ulazni uređaj očitava taj ulaz s upravljačkog programa uređaja koji je priključen na tipkovnicu. Međutim, možete preusmjeriti ili prebaciti ulazni izvor na upravljački program uređaja pridružen datoteci tako da se čini da ulaz "čarobno" dolazi iz datoteke - umjesto s tipkovnice.

Program unosi svoje podatke sa standardnog uređaja za unos pozivajući Javinu System.in.read()metodu. Pogledajte SDK dokumentaciju i otkrit ćete predavanje pod nazivom System. Ta klasa sadrži varijablu koja se naziva in- objekt stvoren iz podklase od InputStream. Znak razdoblja nakon Systemstanja koje inpripada Systemi znak razdoblja nakon instanja koje read()pripada in. Drugim riječima, read()je metoda koja pripada pozvanom objektu in, koji pak pripada klasi koja se zove System. (O klasama, objektima i "pripadnosti" razgovarat ću sljedeći mjesec.)

System.in.read()ne uzima argumente i vraća cijeli broj, što je neke natjeralo da vjeruju da System.in.read()vraća korisnikove cjelobrojne brojeve. Da pojasnimo, System.in.read()vraća 7-bitni ASCII kôd ključa (ako je standardni ulazni uređaj postavljen na tipkovnicu) ili 8-bitni bajt iz datoteke (ako je standardni ulazni uređaj preusmjeren s tipkovnice u datoteku). U oba slučaja System.in.read()pretvara kôd u 32-bitni cijeli broj i vraća rezultat.

Pretpostavimo da je standardni ulazni uređaj postavljen na tipkovnicu. Slijedi opis onoga što se događa u sustavu Windows: Kada tipkate tipku na tipkovnici kojom upravlja Windows, operativni sustav sprema 7-bitni ASCII kôd tog ključa u interni međuspremnik ključa. Taj međuspremnik ključa sadrži do otprilike 16 ASCII kodova i organiziran je kao struktura podataka kružnog reda prvi-prvi-prvi. System.in.read()dohvaća ASCII kôd iz glave međuspremnika ključa, a zatim ga uklanja iz međuspremnika ključa. Taj 7-bitni ASCII kôd zatim se pretvara u int- System.in.read()dodavanjem 25 nultovih bitova u kôd - i vraća pozivatelju metode. System.in.read()Poziv druge metode dohvaća sljedeći ASCII kod, koji je sada na čelu međuspremnika ključa, i tako dalje.

Pretpostavimo da u međuspremniku ključa nema ASCII kodova. Što se događa? System.in.read()čeka da korisnik upiše tipke i pritisne terminator. U sustavu Windows taj je terminator Enterključ. Pritiskom na Entersustav Windows sprema povratni kôd kočije (ASCII 13) nakon kojeg slijedi kôd novog retka (ASCII 10) u međuspremnik ključa. Stoga me uspremnik ključa može sadržavati nekoliko ASCII kodova nakon kojih slijedi vraćanje kočije i znak novog retka. Prvi od tih kodova vraća se iz System.in.read(). Provjerite tu aktivnost unosom, sastavljanjem i pokretanjem Echoaplikacije; njegov izvorni kod pojavljuje se na popisu 1.

Popis 1. Echo.java

// Echo.java klasa Echo {public static void main (String [] args) baca java.io.IOException {int ch; System.out.print ("Unesite tekst:"); while ((ch = System.in.read ())! = '\ n') System.out.print ((char) ch); }}

Echo dovršava sljedeće korake:

  1. Poziva System.out.print()metodu koja uzima Stringargument da izbaci upit
  2. Pozivi System.in.read()za unos ASCII kodova sa standardnog uređaja za unos kao 32-bitni cijeli brojevi
  3. Pretvara te 32-bitne cijele brojeve u 16-bitne Unicode znakove putem (char)emitiranja
  4. Poziva System.out.print()metodu koja uzima charargument da odjekuje te Unicode znakove na standardni izlazni uređaj

Posljednja tri koraka u prethodna četiri koraka odvijaju se u neko vrijeme i nastavljaju se sve dok se ne pročita znak novog retka. Za pokretanje Echotako da se unosi putem tipkovnice i izlaza na zaslon, donosim slijedeću naredbenog retka: java Echo.

Iako System.in.read()nikad ne izuzima iznimku (definiciju tog pojma potražite u temi o brojanju riječi u ovom članku), kada je standardni uređaj za unos postavljen na tipkovnicu, mogao bi izbaciti iznimku kada standardni uređaj za unos preusmjerite s tipkovnice na datoteka. Na primjer, pretpostavimo da standardni uređaj za unos preusmjerite u datoteku i System.in.read()čitate sadržaj iz datoteke. Sada pretpostavimo da se datoteka nalazi na disketi, a korisnik izbacuje taj disk tijekom operacije čitanja. Kada se System.in.read()izvrši izbacivanje, izuzima iznimku, obavještavajući program da ne može pročitati datoteku. To daje razlog za dodavanje throws java.io.IOExceptionklauzule main()zaglavlju metode. (Izuzetke, bacanje iznimaka i srodne koncepte istražit ćete u budućem članku.)

Kako preusmjeriti standardni uređaj za unos tako da unos potječe iz datoteke? Odgovor je uvesti znak manje od <, u naredbeni redak i slijediti taj simbol s imenom datoteke. Da biste vidjeli kako to funkcionira, izdajte sljedeći naredbeni redak:java Echo . The command line redirects the standard input device to a file called Echo.java. When Echo runs, because each line ends in a new-line character, only the first line of text in Echo.java appears on the screen.

Suppose you need a utility program that reads an entire file and either displays the file's contents on the screen, copies those contents to another file, or copies those contents to a printer. Unfortunately, the Echo program only performs that task until it encounters the first new-line character. What do you do? The answer to the problem lies in the Type application. Listing 2 provides the source code:

Listing 2. Type.java

// Type.java class Type { public static void main (String [] args) throws java.io.IOException { int ch; while ((ch = System.in.read ()) != -1) System.out.print ((char) ch); } } 

Type resembles Echo, however, there is no prompt, and the while loop tests against -1 (which indicates end of file) instead of \n (which indicates end of line). To run Type, issue the following command line: java Type . The contents of Type.java -- or whatever file is specified -- will display. As an experiment, try specifying java Type. What do you think will happen? (Hint: this program resembles Echo but doesn't end until you press Ctrl+C.)

Earlier, I mentioned that some programmers mistakenly think that System.in.read() returns a user-entered number. As you've just seen, that isn't the case. But what must you do if you want to use System.in.read() to retrieve a number? Take a look at the Convert application, whose source code is presented in Listing 3.

Listing 3. Convert.java

// Convert.java class Convert { public static void main (String [] args) throws java.io.IOException { System.out.print ("Please enter a number: "); int num = 0; int ch; while ((ch = System.in.read ()) != '\n') if (ch >= '0' && ch <= '9') { num *= 10; num += ch - '0'; } else break; System.out.println ("num = " + num); System.out.println ("num squared = " + num * num); } } 

Listing 3's Convert program prompts the user to enter a number (via System.out.print ("Please enter a number: ");). It reads these digits -- one at a time -- and converts each digit's numeric code to a binary number that is added to a variable called num. Finally, calls to System.out.println() output the value inside num and the square of that value to the standard output device.

Convert demonstrates the time-honored technique of using a while loop to test for a digit, premultiplying a variable by 10 (to make room for the incoming digit), converting a digit to its binary equivalent, and adding that binary equivalent to the variable. However, that technique is not a sound technique to use if you're writing a program for deployment in different countries as some countries use digits other than 0 through 9 -- such as Tamil digits. To make the program operate with other digits, you need to expand the if statement to test for those digits and modify the ch - '0' expression. Fortunately, Java simplifies that task by providing a Character class, which you'll explore in a future article.

Standard output

The standard output device is that part of the operating system that controls where a program sends its output. By default, the standard output device sends the output to a device driver attached to the screen. However, the output destination can be redirected to a device driver attached to a file or printer, which results in the same program displaying its findings on the screen, saving them in a file, or providing a hardcopy listing of the results.

You achieve standard output by calling Java's System.out.print() and System.out.println() methods. Except for the fact that print() methods don't output a new-line character after the data, the two method groups are equivalent. Methods exist to output Boolean, character, character array, double-precision floating-point, floating-point, integer, long integer, string, and object values. To demonstrate these methods, Listing 4 presents source code to the Print application.

Listing 4. Print.java

// Print.java class Print { public static void main (String [] args) { boolean b = true; System.out.println (b); char c = 'A'; System.out.println (c); char [] carray = { 'A', 'B', 'C' }; System.out.println (carray); double d = 3.5; System.out.println (d); float f = -9.3f; System.out.println (f); int i = 'X'; System.out.println (i); long l = 9000000; System.out.println (l); String s = "abc"; System.out.println (s); System.out.println (new Print ()); } } 

Listing 4 has probably triggered some questions for you. First, what is all that System.out. business doing in front of println()? Again, refer to the System class in the SDK documentation. The class contains a variable called out -- an object created from a class called PrintStream. The period character after System indicates that out belongs to System. The period character after out states that println() belongs to out. In other words, println() is a method that belongs to an object called out, which in turn belongs to a class called System.

The second question you might be asking yourself involves println() argument data types: how is it possible for the same println() method to be called with different types of argument data? The answer: because there are several println() methods in the PrintStream class. At runtime, the JVM knows which println() method to call by examining the number of method-call arguments and their data types. (Declaring several methods with the same name but different numbers of arguments and argument data types is known as method overloading. I will discuss that concept next month.)

Finally, you might be wondering about System.out.println (new Print ());. That method call illustrates the println() method, which takes an Object argument. First, the creation operator new creates an object from the Print class and returns a reference to -- also known as the address of -- that object. Finally, that address passes as an argument to the println() method, which takes an Object argument. The method converts the object's contents to a string and outputs that string. By default, the string consists of the name of the object's class, followed by an @ (at) character, followed by a hexadecimal-formatted integer that represents the object's hashcode. (I will present hashcodes and the conversion of objects to strings in an upcoming article.)

Compile Print.java and run the program by issuing the following command line: java Print. You should see nine lines of output. Redirect that output to the out.dat file by issuing the following command line: java Print >out.dat. You can now view the contents of the file.

The greater-than sign, >, indicates standard output redirection. Whenever you want to redirect the standard output device from the screen to a file or printer, specify that symbol followed by the file or printer name on the command line. For example, redirect Print's output to a Windows printer by issuing the following command line: java Print >prn.