Java 101: Seluk-beluk input / output standard
Dalam artikel Java 101 sebelumnya , saya merujuk kepada konsep pengalihan, peranti input standard, dan peranti output standard. Untuk menunjukkan memasukkan data, beberapa contoh disebut System.in.read()
. Ternyata System.in.read()
input data dari peranti input standard. Untuk menunjukkan output data, contoh yang disebut System.out.print()
dan System.out.println()
. Berbeza dengan System.in.read()
orang-orang kaedah - dinamakan urutan kod boleh laku (untuk diterokai dalam artikel bulan depan) - hantar keluaran mereka ke peranti output standard. Ingin mengetahui lebih lanjut mengenai konsep I / O standard? Teruskan membaca!
Standard I / O adalah mekanisme input / output piawai yang berasal dari sistem operasi Unix. Walaupun mekanisme ini kebanyakan digunakan dengan sistem operasi non-GUI yang lebih tua, I / O standard tetap memainkan peranan dalam sistem operasi GUI moden (antara muka pengguna grafik), di mana orang menggunakannya untuk men-debug program yang tidak berfungsi dan untuk mengajar input / output dalam entri- kursus pengaturcaraan peringkat.
Seperti yang mungkin anda sangka, I / O standard menggunakan peranti untuk memasukkan dan mengeluarkan data. Peranti ini merangkumi input standard, output standard, dan kesalahan standard.
Input standard
The peranti input standard adalah bahawa sebahagian daripada sistem operasi bahawa kawalan dari mana program menerima input. Secara lalai, peranti input standard membaca bahawa input dari pemacu peranti yang dipasang pada papan kekunci. Namun, anda boleh mengalihkan, atau menukar, sumber input ke pemacu peranti yang dilampirkan pada fail sehingga input nampaknya "ajaib" berasal dari fail - bukannya papan kekunci.
Program memasukkan datanya dari peranti input standard dengan memanggil System.in.read()
kaedah Java . Lihat dalam dokumentasi SDK dan anda akan menemui kelas yang dipanggil System
. Kelas itu mengandungi pemboleh ubah yang disebut in
- objek yang dibuat dari subkelas InputStream
. Watak noktah selepas System
menyatakan yang menjadi in
miliknya System
, dan watak noktah setelah in
menyatakan yang menjadi read()
milik in
. Dengan kata lain, read()
adalah kaedah yang termasuk dalam objek yang disebut in
, yang pada gilirannya termasuk dalam kelas yang disebut System
. (Saya akan membincangkan lebih lanjut mengenai kelas, objek, dan "kepunyaan" bulan depan.)
System.in.read()
tidak memberikan argumen dan mengembalikan bilangan bulat, yang menyebabkan beberapa orang percaya bahawa System.in.read()
mengembalikan nombor bulat yang dimasukkan pengguna. Untuk menjelaskan, System.in.read()
sama ada mengembalikan kod ASCII 7-bit kunci (jika peranti input standard ditetapkan ke papan kekunci) atau bait 8-bit dari fail (jika peranti input standard telah dialihkan dari papan kekunci ke fail). Dalam kedua-dua kes, System.in.read()
menukar kod menjadi bilangan bulat 32-bit dan mengembalikan hasilnya.
Andaikan bahawa peranti input standard ditetapkan ke papan kekunci. Berikut ini adalah penerangan tentang apa yang berlaku di Windows: Apabila anda mengetik kekunci pada papan kekunci yang dikendalikan oleh Windows, sistem operasi menyimpan kod ASCII 7-bit kunci itu dalam penyangga kunci dalaman. Penyangga kunci itu memuat kira-kira 16 kod ASCII dan disusun sebagai struktur data barisan bulat pertama / keluar. System.in.read()
mengambil kod ASCII dari kepala penyangga kunci dan kemudian mengeluarkan kod itu dari penyangga kunci. Kod ASCII 7-bit itu kemudian bertukar menjadi int
- dengan System.in.read()
menambahkan 25 bit sifar ke kod - dan kembali ke pemanggil kaedah. System.in.read()
Panggilan kaedah kedua mengambil kod ASCII seterusnya, yang kini berada di kepala penyangga kunci, dan seterusnya.
Katakan tidak ada kod ASCII dalam penyangga kunci. Apa yang berlaku? System.in.read()
menunggu pengguna menaip kekunci dan tekan terminator. Di bawah Windows, terminator itu adalah Enter
kuncinya. Menekan Enter
menyebabkan Windows menyimpan kod pengembalian kereta (ASCII 13) diikuti dengan kod baris baru (ASCII 10) dalam penyangga kunci. Oleh itu, penyangga kunci mungkin mengandungi beberapa kod ASCII diikuti dengan kembalinya kereta dan watak barisan baru. Yang pertama dari kod tersebut kembali dari System.in.read()
. Lihat aktiviti itu dengan memasukkan, menyusun, dan menjalankan Echo
aplikasi; kod sumbernya muncul dalam Penyenaraian 1.
Penyenaraian 1. Echo.java
// Echo.java class Echo {public static void main (String [] args) melemparkan 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:
- Memanggil
System.out.print()
kaedah yang memerlukanString
argumen untuk mengeluarkan arahan - Panggilan
System.in.read()
untuk memasukkan kod ASCII dari peranti input standard sebagai bilangan bulat 32-bit - Menukar bilangan bulat 32-bit menjadi watak Unicode 16-bit dengan cara
(char)
pemeran - Memanggil
System.out.print()
kaedah, yang memerlukanchar
argumen, untuk menggemakan watak-watak Unicode tersebut ke peranti output standard
Tiga langkah terakhir dalam empat langkah sebelumnya berlaku dalam beberapa saat, dan teruskan sehingga watak baris baru dibaca. Untuk menjalankan Echo
supaya ia input daripada papan kekunci dan output ke skrin, mengeluarkan baris arahan berikut: java Echo
.
Walaupun System.in.read()
tidak pernah memberikan pengecualian (lihat topik penghitungan kata dalam artikel ini untuk definisi istilah itu), apabila peranti input standard ditetapkan ke papan kekunci, ia mungkin membuang pengecualian ketika anda mengalihkan peranti input standard dari papan kekunci ke fail. Sebagai contoh, anggap anda mengalihkan peranti input standard ke fail, dan System.in.read()
membaca kandungan dari fail tersebut. Sekarang anggap fail tersebut terletak pada disket, dan pengguna mengeluarkan cakera tersebut semasa operasi membaca. Ketika ejeksi berlaku, System.in.read()
melontarkan pengecualian, memberitahu program bahawa mereka tidak dapat membaca fail. Itu memberikan alasan untuk menambahkan throws java.io.IOException
klausa ke main()
tajuk kaedah. (Anda akan meneroka pengecualian, membuang pengecualian, dan konsep yang berkaitan dalam artikel yang akan datang.)
Bagaimana anda mengalihkan peranti input standard sehingga input berasal dari fail? Jawapannya adalah dengan memperkenalkan tanda kurang dari <
pada baris perintah dan ikuti simbol itu dengan nama fail. Untuk melihat cara kerjanya, keluarkan baris arahan berikut:java Echo
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
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
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
.