Từ trớc đến giờ ta vẫn thờng hay in dữ liệu ra màn hình bằng cách gọi : System.out.println ( ) ;
System.out chính là một đối tợng thuộc lớp luồng xuất (chính xác là luồng PrintStream). Nh mọi lớp luồng xuất bình thờng khác nó cũng có thể kết hợp với các luồng trung gian. Dới đây là ví dụ minh họa để bạn thấy rõ điều
đó. Ta vẫn có thể ghi ra màn hình mà không cần dùng đến hàm print ( ) hay println ( ) của đối tợng System.out.
21. Đối tợng system.in
System.in lại là một đối tác đặc biệt ra đời từ lớp InputStream. Nó giúp ta đọc các ký tự đợc ngời dùng gõ vào từ bàn phím . là một luồng nhập nên ta có thể đọc dữ liệu từ đối tợng thuộc System . in một cách bình thờng bằng phơng thức read ( ) hay bằng cách kết nối với một luồng trung gian khác . Dới dây là ví dụ minh họa cho cách tiếp nhận dữ liệu từ bàn phím đa vào bằng đối tợng System.in :
Ví dụ 11-17 SystemInApp.java Chơng trình đọc dữ liệu đánh vào từ bàn phím
import java . io .* ;
public class SystemInApp [ public static void main ( String args [ ] ) throws IOExceptio
// Đọc một chuỗi nhập từ bàn phím bằng cách dùng bộ đệm
System . out . print ( “ Please enter astring :”) ; Byte [ ] buffer = new byte [255] ;
int charCount = System . in . read ( buff , 0 , 255 ) ; for ( int I = 0 ; I < charCount ; i + +)
System . out .print ( ( char) buff [i] ) ;
// Đọc một chuỗi nhập từ bàn phím bằng kỹ thuật luồng
DataInputStream bStream = new
DataInputStream ( System . in) ; System . out . print (“Please enter a String :”) System . out . println ( bStream . readLine ( ) ) ; }
}
Với chơng trình trên ta có hai cách để đọc dữ liệu từ bàn phím đa vào . Cách thứ nhất là dùng một vùng đệm buff dàI 255 byte và gọi phơng thức read ( ) để đa dữ liệu mà đối tợng System .in nhận đợc từ bàn phím vào buff . Sau đó lấy các ký tự từ buff ra để xử lý .
Cách thứ hai là ta dùng luồng DataInputStream tiếp nhận dữ liệu từ đối tợng System.in . Lớp DataInputStream có khả năng đọc mỗi lần một dòng văn bản bằng lệnh readLine ( ) và trả về một chuỗi . Tuy nhiên phơng thức readLine() dùng cho lớp DataInputStream có lẽ trong tơng lai các nhà phát triển Java không còn hỗ trợ cho nó nữa (nên chơng trình javac mới đa ra
mọt lời cảnh báo khi biên dịch ) . Ta sử dụng phơng thức readLine ( ) từ lớp bufferedReader , lớp này giúp việc chuyển đổi giữa các ký tự hai byte Unicode dễ dàng hơn ( ta sẽ nghiên cứu về các lớp luồng xử lý những ký tự Unicode 2 byte ở phần dới ) .
22 . Lớp objectoutputstream
ở những phần trớc ta đã dùng các đối tợng thuộc lớp DataOutputStream để ghi những điều sơ cấp nh: int, char, float, double.. xuống tập tin. Sẽ đến một lúc ta có nhu cầu ghi luôn cả đối tợng xuống tập tin để hôm sau có thể đọc lại đối tợng đó với trạng thái đã lu lần trớc. Điều này rất có ý nghĩa, chẳng hạn đối với những bộ công cụ phát triển phần mềm trực quan (visual) nh Jbuilder, Visual Basic, Delphi..khi thiết kế chơng trình ta sử dụng từng đối tợng nh nút ấn (button), ô điều khiển (checkbox), văn bản (text, memo)..đặt lên biểu mẫu(from) để tô vẽ giao diện cho ứng dụng. Nếu đóng tập tin ở dự án (project file) lại và mở lên lần sau bạn sẽ thấy các đối tợng vẫn ở trong trạng tháI y nguyên nh đang làm dở dang trớc đó. Java cung cấp cho ta lớp ObjectOutputStream để thực hiện khả năng này. Lớp ObjectOutputStream ngoài khả năng ghi đợc các kiểu dữ liệu sơ cấp xuống tập tin nh lớp DataOutputStream nó còn có khả năng ghi đợc cả những đối tợng nhờ phơng thức mạnh mẽ là writeObject ( ) đợc khai báo nh sau
public void writeObject (Object obj) throws ClassMismatchException,
MethodMissingException, IOException
Sở dĩ có khả nằng này là vì ObjectOutputStream chính là lớp con của lớp DataInputStream( nó chỉ bổ sung thêm chức năng writeObject ( ) mà lớp dataOutputStreamkhông có). Chính vì thế ObjectOutputStream cũng dợc coi là một luồng trung gian và có thể kết nối với bất kỳ luồng xuất nào khác thuộc lớp Outputtream.
Tuy nhiên có một điều cần lu ý là cácđối tợng muốn ghi đợc xuống tập tin phải thuộc những lớp có cài đặt giao tiếp (inferface) Serializable. Lớp giao tiếp Serializable quy định những ràng buộc mà một đối tợng có thể đợc ghi xuống và đọc lên từ tập tin.
Dới đây là ví dụ minh họa cho cách ghi các đối tợng khác nhau xuống tập tin. Các đối tợng này sẽ đợc này sẽ đọc lên trở lại bằng chơng trình ObjectReadApp.java sẽ đợc viết ngay sau phần tiếp theo :
Ví dụ 11-18: ObjectWriteApp.java chơng trình ghi các đối tợng xuống tập tin
import java.io.*; import java.util.*;
public class ObjectWriteApp {
public static void main (String args[ ]} throws IOException {
ObjectOutputStream oStream = new ObjectOutputStream {
new FileOutputStream (“ Container.txt”));
// Lần lợt ghi các đối tợng khác nhau xuống tập tin
oStream.writeObject ( new String (“Hello world ”)); oStream.writeObject ( new Fruit (“Orange”, 10)); oStream.writeObject (new Fruit ( “ Apple”,5)); oStream.writeObject (new Date ( ));
System.out.println (“ Total 4 objects written to Container.txt”);
} }
// Lớp đối tợng tự tạo
class Fruit implements Serializable { String name = “ ”;
int weight = 0
public Fruit (String n ,int w) { name = n ;
weight = w; }
public String toString ( ) {
return ( name + “ ” +weight+ “g”) }
}
Biên dịch
C : \ Learning > javac ObjectWriteApp.java Chạy chơng trình
C : \ Learning > java ObjectWriteApp Total 4 objects written to Container.txt
Với chơng trình trên trớc hết ta tự thiết kế cho mình một lớp Fruit để tạo ra các loại tráI cây khác nhau, mỗi tráI là một đối tợng có tên ( name) và trọng lợng (weight).phơng thức toString ( ) dùng để chuyển các dặc tính của đối
tợng trái cây thành một chuỗi để biểu hiện. Nh đã nói muốn các đối tợng thuộc lớp Fruit để ghi xuống tập tin đợc ta cài đặt giao tiếp Serializable cho nó.
ở lớp chơng trình chính, một tập tin tên Container.txt đợc tạo ra và gắn vào luồng oStream thuộc lớp ObjectOutputStream. Ta dùng luồng oStreamlần l- ợt ghi các đối tợng khác nhau xuống tập tin, đầu tiên là một chuỗi tiếp đến là một tráI cam nặng 10g ( Fruit (“ Orange”,10)), một tráI táo nặng 5g(Fruit(“Apple”, 5)) và một đối tợng là ngày giờ hiện hành Date ( Date là lớp thuộc lớp th viện java.utilmà ta đã khai báo sử dụng ở phần đầu importjava.util.*) Khi chạy chơng trình này tổng cộng sẽ có 4 đối tợng đã đợc ghi vào tập tin Container.txt
Một điều cần lu ý là phơng thức toString ( ) của lớp Fruit, bất cứ đối tợng nào cũng có sẵn phơng thức toString ( ) kế thừa từ lớp thủy tổ Object. Nếu muốn hàm System.out.println ( ) có thể in những thông tin dặc trng. Chẳng hạn ta có thể viết:
Fruit orange = new Fruit (“ Orange” ,10) ; System.out.println (“ My object :” +orange); Kết quả in ra là
My object : Orange 10g
Nh bạn thấy “My object :” là một chuỗi mà ta vẫn có thể cộng đợc với một kiểu đối tợng (orange), trong những trờng hợp này Java sẽ gọi hàm toString () của đối tợng dới dạng chuỗi rồi mới cho thực hiện phép cộng. Mọi việc đều ổn thỏa, không có lỗi sai kiểu dữ liệu ở đây
23. Lớp ObjectInputStream
Phần trên ta đã ghi đợc các đói tợng xuống tập tin. Tiếp theo ta sẽ khảo sát xem các đối tợng sẽ đợc đọc trở lại nh thế nào? Lớp “đối tác” của ObjectOutputStream là objectInputStream sẽ giúp bạn thực hiện điều đó. D- ới đây là chơng trình minh họa:
Ví dụ 11-19 ObjectReadApp.java Chơng trình đọc các đối tợng từ tập tin
import java.io.*;
public class ObjectReadApp {
public static void main (String args [ ] ) throws Exception { ObjectInputStream Ostream = new ObjectInputStream ( new File InputStream (“ Container.txt”));
int oCount = 0; try {
while (true) {
System.out.println (oStream.readObject ( ) ); oCount ++;
}
} catch ( EOFException e ){
System.out.println (“Total read”+oCount+” Objects”); }
} }
Biên dịch
C : \ Learning > javac ObjectReadApp.java Chạy chơng trình
C : \ Learning > java ObjectReadApp Hello worrld
Orange 10g Apple 5g
Tue Feb 09 15:21:37 PST 1999 Total read 4 objects
Chơng trình ObjectReadApp.java rất đơn giản. Nó chỉ việc mở tập tin Container.txt ( đã ghi ở chơng trình trớc), gắn vào luồng oStream, sau đó liên tục đọc các đối tợng từ luồng và cho in ra màn hình. Việc đọc dữ liệu từ luồng không nhất thiết phải xem hàm read ( ) có trả về giá trị –1 cho biết đã đến cuối luồng hay cha. Ta có thể sử dụng vòng lặp bất tận để đọc dữ liệu cho đến khi nào không còn gì cả thì Java sẽ ném ra một ngoại lệ EOFException, bắt lấy ngoại lệ này cũng sẽ biết đợc quá trình đọc đẫ đến cuối tập tin. Đây chính là cách mà chơng trình trên sử dụng.