Java 101: Seluk beluk standar input / output

Dalam artikel Java 101 sebelumnya , saya mengacu pada konsep pengalihan, perangkat input standar, dan perangkat output standar. Untuk mendemonstrasikan penginputan data, beberapa contoh dipanggil System.in.read(). Ternyata System.in.read()input data dari perangkat input standar. Untuk mendemonstrasikan data keluaran, contoh dipanggil System.out.print()dan System.out.println(). Berbeda dengan System.in.read(), metode tersebut - dinamai urutan kode yang dapat dieksekusi (akan dieksplorasi di artikel bulan depan) - mengirim outputnya ke perangkat output standar. Ingin tahu lebih banyak tentang konsep I / O standar? Baca terus!

Standar I / O adalah mekanisme input / output standar yang berasal dari sistem operasi Unix. Meskipun mekanisme ini sebagian besar digunakan dengan sistem operasi non-GUI yang lebih lama, I / O standar masih berperan dalam sistem operasi GUI (antarmuka pengguna grafis) modern, di mana orang menggunakannya untuk men-debug program yang tidak berfungsi dan untuk mengajarkan input / output di entri- kursus pemrograman tingkat.

Seperti yang mungkin Anda duga, I / O standar menggunakan perangkat untuk memasukkan dan mengeluarkan data. Perangkat ini termasuk input standar, output standar, dan kesalahan standar.

Masukan standar

Perangkat input standar adalah bagian dari sistem operasi yang mengontrol dari mana program menerima inputnya. Secara default, perangkat input standar membaca input tersebut dari driver perangkat yang terpasang ke keyboard. Namun, Anda dapat mengalihkan, atau mengalihkan, sumber input ke driver perangkat yang dilampirkan ke file sehingga input tampak "secara ajaib" berasal dari file - bukan dari keyboard.

Sebuah program memasukkan datanya dari perangkat input standar dengan memanggil System.in.read()metode Java . Lihat di dokumentasi SDK dan Anda akan menemukan kelas bernama System. Kelas itu berisi variabel yang disebut in- objek yang dibuat dari subkelas InputStream. Karakter titik setelah Systemkeadaan yang indimiliki System, dan karakter titik setelah inkeadaan yang read()dimiliki in. Dengan kata lain, read()adalah metode yang dimiliki oleh suatu objek yang disebut in, yang pada gilirannya menjadi milik kelas yang disebut System. (Saya akan membahas lebih lanjut tentang kelas, objek, dan "milik" bulan depan.)

System.in.read()tidak mengambil argumen dan mengembalikan integer, yang membuat beberapa orang percaya bahwa System.in.read()mengembalikan bilangan integer yang dimasukkan pengguna. Untuk memperjelas, System.in.read()mengembalikan kode ASCII 7-bit kunci (jika perangkat input standar disetel ke keyboard) atau byte 8-bit dari file (jika perangkat input standar telah dialihkan dari keyboard ke file). Dalam kedua kasus tersebut, System.in.read()ubah kode menjadi integer 32-bit dan kembalikan hasilnya.

Asumsikan bahwa perangkat input standar diatur ke keyboard. Berikut ini adalah deskripsi tentang apa yang terjadi di bawah Windows: Ketika Anda mengetikkan kunci pada keyboard yang dikontrol Windows, sistem operasi menyimpan kode ASCII 7-bit kunci itu di buffer kunci internal. Buffer kunci tersebut menampung hingga sekitar 16 kode ASCII dan diatur sebagai struktur data antrian melingkar pertama masuk / keluar pertama. System.in.read()mengambil kode ASCII dari kepala buffer kunci dan kemudian menghapus kode tersebut dari buffer kunci. Kode ASCII 7-bit itu kemudian diubah menjadi int- dengan System.in.read()menambahkan 25 bit nol ke kode sebelumnya - dan kembali ke pemanggil metode. Pemanggilan System.in.read()metode kedua mengambil kode ASCII berikutnya, yang sekarang berada di head buffer kunci, dan seterusnya.

Misalkan tidak ada kode ASCII di buffer kunci. Apa yang terjadi? System.in.read()menunggu pengguna mengetik kunci dan menekan terminator. Di bawah Windows, terminator itu adalah Enterkuncinya. Menekan Entermenyebabkan Windows menyimpan kode kembali kereta (ASCII 13) diikuti dengan kode baris baru (ASCII 10) di buffer kunci. Oleh karena itu, buffer kunci mungkin berisi beberapa kode ASCII yang diikuti dengan carriage return dan karakter baris baru. Kode pertama kembali dari System.in.read(). Periksa aktivitas itu dengan memasukkan, menyusun, dan menjalankan Echoaplikasi; kode sumbernya muncul di Listing 1.

Daftar 1. Echo.java

// Kelas Echo.java Echo {public static void main (String [] args) melempar java.io.IOException {int ch; System.out.print ("Masukkan beberapa teks:"); sementara ((ch = System.in.read ())! = '\ n') System.out.print ((char) ch); }}

Echo menyelesaikan langkah-langkah berikut:

  1. Memanggil System.out.print()metode, yang membutuhkan Stringargumen, untuk mengeluarkan prompt
  2. Panggilan System.in.read()untuk memasukkan kode ASCII dari perangkat masukan standar sebagai bilangan bulat 32-bit
  3. Mengonversi bilangan bulat 32-bit tersebut menjadi karakter Unicode 16-bit melalui (char)cast
  4. Memanggil System.out.print()metode, yang mengambil charargumen, untuk menggemakan karakter Unicode tersebut ke perangkat keluaran standar

Tiga langkah terakhir dalam empat langkah sebelumnya berlangsung dalam perulangan while, dan berlanjut hingga karakter baris baru terbaca. Untuk menjalankan Echosehingga masukan dari keyboard dan output ke layar, mengeluarkan baris perintah berikut: java Echo.

Meskipun System.in.read()tidak pernah memberikan pengecualian (lihat topik penghitungan kata dalam artikel ini untuk definisi istilah tersebut), ketika perangkat input standar disetel ke keyboard, perangkat ini mungkin memunculkan pengecualian saat Anda mengalihkan perangkat input standar dari keyboard ke file. Misalnya, Anda mengarahkan perangkat input standar ke sebuah file, dan System.in.read()membaca konten dari file tersebut. Sekarang misalkan file tersebut terletak pada floppy disk, dan pengguna mengeluarkan disk itu selama operasi baca. Saat ejeksi terjadi, System.in.read()melontarkan pengecualian, memberi tahu program bahwa ia tidak dapat membaca file. Itu memberikan alasan untuk menambahkan throws java.io.IOExceptionklausa ke main()header metode. (Anda akan mempelajari pengecualian, melempar pengecualian, dan konsep terkait di artikel mendatang.)

Bagaimana Anda mengarahkan perangkat input standar sehingga input berasal dari sebuah file? Jawabannya adalah dengan memasukkan tanda kurang dari <,, pada baris perintah dan ikuti simbol itu dengan nama file. Untuk melihat cara kerjanya, keluarkan baris perintah berikut ini: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.