Hiển thị các bài đăng có nhãn Tài Liệu. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Tài Liệu. Hiển thị tất cả bài đăng

Bài 7: Thẻ tạo form trong html

Lukaku 19:05 Add Comment
Thẻ form trong html là thẻ giữ vai trò tương tác giữa người dùng và website. Trong bài học này, chúng ta sẽ cùng tìm hiểu cách sử dụng thẻ form để tạo 7 dạng giao diện form cơ bản. ( còn phần xử lý form sẽ được học trong ngôn ngữ php )

Khai báo thẻ Form

 form username trong html

Form nhập username

 form username trong html
Với type="text" là nhập các kí tự từ bàn phím, size="25" là độ dài khung bằng 25.

Form nhập password

 form password trong html
Với type="password" là các kí tự sẽ được thay thế bằng ***, size="25" là độ dài khung bằng 25.

Form textarea

 form textarea trong html
Với rows="..." là chiều cao, cols="..." là chiều ngang.
Dạng form textarea này chúng ta có thể nhập đoạn văn dài vào đây.
Thường được dùng để tạo khung comment hoặc là khung đóng góp ý kiến.

Form select, option

 form select trong html
Dạng này thường được dùng chọn ngày tháng năm sinh...v.v

Form radio

 form radio trong html
Dạng này thường được dùng để tạo form lựa chọn giới tính.

Form checkbox

 form checkbox trong html
Dạng này chúng ta có thể check nhiều lựa chọn cùng lúc. Khác với form radio chỉ chọn được 1.

Form submit

 form submit trong html
Với value="login" tức là button submit sẽ có tên hiển thị là "login".
Xem hướng dẫn chi tiết trong video phía dưới:


Nguồn: 2school.vn

Bài 6: Thẻ tạo bảng trong html

Lukaku 19:03 Add Comment
Để tạo bảng trong html người ta sử dụng thẻ table. Một table sẽ bao gồm nhiều dòng và nhiều cột được xác định bằng thẻ tr và thẻ td.

Thẻ table trong html

 thẻ table trong html

Khai báo thẻ tr để tạo dòng.

 tạo dòng

Khai báo thẻ td để tạo cột.

 ví dụ table

Viết thuộc tính border để tạo khung cho table.

 border table trong html
Xem hướng dẫn chi tiết trong video phía dưới:


Nguồn: 2school.vn

Bài 5: Thẻ danh sách trong html

Lukaku 18:28 Add Comment
Trong html, thẻ danh sách được dùng để tạo ra một danh sách các bài viết để người dùng lựa chọn giống như hình dưới.
 thẻ ol li trong html
Có tất cả 3 dạng danh sách mà các bạn cần phải học.

Danh sách có thứ tự

Cách viết:
 thẻ ol li trong html

Danh sách không có thứ tự

Cách viết:
 thẻ ul li trong html
Dạng thẻ ul, li này được sử dụng nhiều nhất

Danh sách lồng nhau

Cách viết:
 danh sách lồng nhau trong html
Dạng này thường được sử dụng làm menu left
Xem hướng dẫn chi tiết trong video phía dưới:


Nguồn: 2school.vn

Bài 4: Thẻ chuyển liên kết trong html

Lukaku 18:26 Add Comment
Trong HTML, để website chuyển từ bài viết này sang bài viết khác thì chúng ta sẽ sử dụng thẻ liên kết. Cách viết thẻ liên kết cũng tương đối giống với thẻ hình ảnh ở bài 3.

Thẻ liên kết

Cách viết:
 thẻ liên kết trong html
Khi chúng ta click vào "click here" thì website sẽ chuyển liên kết "đến đường dẫn liên kết".
Đường dẫn của thẻ liên kết cũng giống đường dẫn của thẻ hình ảnh.
Được chia làm 2 loại: đường dẫn tuyệt đối và đường dẫn tương đối

Đường dẫn tuyệt đối

Tuyệt đối tức là không thay đổi.
Loại đường dẫn này chúng ta sẽ copy nó ở trên thanh địa chỉ của trình duyệt web.
Cách viết:
 đường dẫn tuyệt đối trong html
Nhận xét: đường dẫn tuyệt đối bắt đầu bằng http://

Đường dẫn tương đối

Tương đối tức là sẽ thay đổi.
Loại đường dẫn này chúng ta sẽ tự viết ra.
Cách viết: có tất cả 4 kiểu viết đường dẫn tương đối
 đường dẫn tương đối trong html
Nhận xét: đường dẫn tương đối không có http://
Đặc biệt
Nếu chúng ta không có đường dẫn cụ thể thì chúng ta sẽ sử dụng dấu # để thay thế.
Cách viết
 dấu thăng trong thẻ liên kết

Thuộc tính target = "..."

Tác dụng: khi click chuột thì liên kết sẽ được mở ra trên một tab mới.
Cách viết:
 thuộc tính target
Xem hướng dẫn chi tiết trong video phía dưới:


Nguồn: 2school.vn

Bài 3: Thẻ chèn hình ảnh trong html

Lukaku 18:24 Add Comment
Trong html, để hiển thị hình ảnh lên website người ta dùng thẻ img. Khi học về thẻ hình ảnh này, các bạn chú ý kĩ cách lấy đường dẫn tương đối và tuyệt đối trong thuộc tính src.

Thẻ hình ảnh

Cách viết:
 thẻ hình ảnh trong html
Đường dẫn tấm hình được chia làm 2 loại: đường dẫn tuyệt đối và đường dẫn tương đối

Đường dẫn tuyệt đối

Tuyệt đối tức là không thay đổi.
Loại đường dẫn này chúng ta sẽ copy nó ở trên thanh địa chỉ của trình duyệt web.
Cách viết:
 đường dẫn tuyệt đối trong html
Nhận xét: đường dẫn tuyệt đối bắt đầu bằng http://

Đường dẫn tương đối

Tương đối tức là sẽ thay đổi.
Loại đường dẫn này chúng ta sẽ tự viết ra.
Cách viết: có tất cả 4 kiểu viết đường dẫn tương đối
 đường dẫn tương đối  trong html
Nhận xét: đường dẫn tương đối không có http://
Resize tấm hình
Chúng ta sẽ sử dụng thuộc tính width(chiều rộng) và height(chiều cao) để thu nhỏ hay phóng to tấm hình.
Cách viết
 thuộc tính của thẻ hình ảnh trong html
Xem hướng dẫn chi tiết trong video phía dưới:


Nguồn: 2school.vn

Bài 2: Các thẻ cơ bản trong html

Lukaku 18:21 Add Comment
HTML có hàng trăm thẻ tag khác nhau. Việc học hết các thẻ html là không cần thiết. Về cơ bản các bạn chỉ nên học các thẻ thường dùng là có thể viết được một website. Sau đây là các thẻ html thường dùng đã được tổng hợp.

Heading - Thẻ tiêu đề

Heading gồm 6 loại từ h1 đến h6.
Cách viết:
 thẻ h1 h3 h3 h4 h5 trong html
Các thẻ heading có kích thước giảm dần từ h1 tới h6

Paragraph - Thẻ đoạn văn

Một trang HTML (như trang tin tức) được chia thành nhiều đoạn văn khác nhau, mỗi đoạn được xác định bởi thẻ <p> và thẻ <p> tự động xuống dòng khi hết một đoạn văn.
Cách viết:
 thẻ p trong html

Thẻ in đậm, in ngiêng, gạch dưới

Cách viết:
 thẻ in đậm in nghiêng gạch dưới trong html

Thẻ xuống hàng

Cách viết:
 thẻ xuống hàng trong html
Khi viết thẻ xuống hàng, chúng ta không nên chỉ viết là <br> thôi, mà phải viết là <br /> mới đúng chuẩn w3c.
Xem hướng dẫn chi tiết trong video phía dưới:



Nguồn: 2school.vn

Bài 1: Tổng quát về ngôn ngữ html

Lukaku 18:18 Add Comment
HTML là ngôn ngữ cơ bản cần phải học để thiết kế website. Bạn có thể xây dựng nội dung website hay không là nhờ vào html. Nó gần như là một thành phần không thể thiết trong mọi trang web.

HTML là gì?

Hiểu đơn giảm: HTML là thành phần dùng để xây dựng nội dung giao diện cho website.
Về định nghĩa:
  • HTML là ngôn ngữ đánh dấu siêu văn bản (Hyper Text Markup Language).
  • Do Tim Berner Lee phát minh và được W3C (World Wide Web Consortium) đưa thành chuẩn năm 1994.
  • File HTML là 1 text file (file văn bản) có chứa các thẻ (tag).
  • File HTML sẽ có phần đuôi là .html

Phần mềm Dreamweaver

Có rất nhiều phần mềm hỗ trợ viết html, css, php: notepad++, neatbean, eclipse, ...
Ở đây website sẽ sử dụng Dreamweaver CS3 để viết code. (hiện tại đã có phiên bản CS6)
 Dreamweaver CS3

Thẻ tag trong html

Thẻ được dùng để hiển thị phần nội dụng chúng ta viết lên trình duyệt web.
Cách viết một thẻ: <ten_the>. Ví dụ: <html> được gọi là thẻ html.
Có 2 dạng thẻ: thẻ đơn và thẻ kép.
Thẻ đơn là thẻ chỉ có thẻ bắt đầu. Ví dụ: thẻ <br />.
Thẻ kép là thẻ có thẻ bắt đầu và thẻ kết thúc. Ví dụ: thẻ <p>noi_dung</p>.
Khi nào dùng thẻ đơn và khi nào dùng thẻ kép?
Trong HTML phần lớn là chúng ta sử dụng thẻ kép, còn thẻ đơn chỉ có 1 số ít.
Thẻ đơn giống như động từ bất quy tắc trong tiếng anh các bạn phải học thuộc để sử dụng cho đúng.

Cấu trúc file *.html

Đầu tiên, viết file html thì chúng ta phải khai báo cặp thẻ html.
 thẻ html
Mỗi file html cần một thẻ head.
 thẻ head trong html
Trong thẻ head sẽ có thẻ title dùng để viết tên website.
 thẻ title trong html
Và cuối cùng phần nội dung trang web chúng ta sẽ viết trong thẻ body.
 thẻ body trong html
Trình duyệt hiển thị.
 ví dụ html
Xem hướng dẫn chi tiết trong video phía dưới:


                                                                                                                            Nguồn:2school.vn

QUẢN LÝ CÁC LUỒNG VÀO RA

Lukaku 22:20 Add Comment

1.1             Giới thiệu

            Một chương trình máy tính cần phải lấy dữ liệu từ bên ngoài vào chương trình để xử lý. Sau khi chương trình xử lý xong sẽ xuất kết quả ra ngoài cho thành phần khác để tiếp tục xử lý hoặc lưu trữ. Dữ liệu được truyền từ chương trình này sang chương trình khác bằng các luồng dữ liệu. Để cài đặt việc truyền dữ liệu này, Java cung cấp package java.iovới rất nhiều lớp và các tính năng phong phú.
            Xét theo loại dữ liệu, Java chia các luồng thành hai loại là luồng byte (byte stream) và luồng ký tự (character stream). Giữa hai loại dữ liệu này có các lớp trung gian để phục vụ cho việc chuyển đổi.
            Xét theo thao tác, Java chia các luồng thành hai loại là input (đọc byte) và output(ghi byte) hoặc reader (đọc character) và writer (ghi character).

Byte streams
Character streams
Source streams
InputStream
Reader
Sink streams
OutputStream
Writer
Các stream cơ bản trong Java
Ngoài ra, Java còn hỗ trợ rất nhiều luồng hỗ trợ cho việc đọc ghi khác.
Minh họa các nguồn dữ liệu

1.2             Các luồng Byte

            Các luồng byte có chức năng đọc hoặc ghi dữ liệu dạng byte. Dựa vào thao tác, các luồng byte được chia ra hai loại chính: nhóm input được đại diện bởi lớp InputStream và nhóm output được đại diện bởi OutputStream. Các lớp xử lý trên luồng byte đều được kế thừa từ hai lớp này.

Sơ đồ tổ chức của các stream đọc byte

Sơ đồ tổ chức của các stream ghi byte

1.2.1       Các luồng byte tổng quát

            Gồm các lớp InputStreamOutputStream. Đây hai là lớp trừu tượng, nó quy định các phương thức đọc và ghi dữ liệu dạng byte và một số phương thức hỗ trợ khác:
Phương thức
Ý nghĩa
Lớp InputStream
int available()
Trả về số byte còn lại trong stream.
void close()
Đóng stream.
void mark(int readlimit)
Đánh dấu vị trí hiện tại. Nếu sau khi mark ta đọc quá readlimit byte thì chỗ đánh dấu không còn hiệu lực.
boolean markSupported()
Trả về true nếu stream hỗ trợ markreset.
abstract int read()
Đọc byte kế tiếp trong stream.
Quy ước: Trả về -1 nếu hết stream.
Đây là phương thức trừu tượng.
int read(byte[]buffer)
Đọc một dãy byte và lưu kết quả trong mảng buffer. Số byte đọc được tối đa là sức chứa (length) của buffer. Nếu buffer có sức chứa là 0 thì sẽ không đọc được gì.
Sau khi đọc xong sẽ trả về số byte đọc được thật sự (nếu đang đọc mà hết stream thì số byte đọc được thật sự sẽ nhỏ hơn sức chứa của buffer).
Nếu stream đã hết mà vẫn đọc nữa thì kết quả trả về là -1.
int read(byte[]buffer, int offset, int len)
Đọc một dãy byte và lưu kết quả trong mảng buffer kể tự byte thứ offset. Số byte đọc được tối đa là len. Nếu len là 0 thì sẽ không đọc được gì.
Sau khi đọc xong sẽ trả về số byte đọc được thật sự (nếu đang đọc mà hết stream thì số byte đọc được thật sự sẽ nhỏ hơn len).
Nếu stream đã hết mà vẫn đọc nữa thì kết quả trả về là -1.
void reset()
Trở lại chỗ đã đánh dấu bằng phương thức mark().
long skip(long n)
Bỏ qua n byte (để đọc các byte tiếp sau n byte đó).
Lớp OutputStream
void close()
Đóng stream.
void flush()
Buộc stream ghi hết dữ liệu trong vùng đệm ra ngoài.
void write(byte[]buffer)
Ghi một dãy byte vào stream. Số byte được ghi sẽ là buffer.length.
int write(byte[]buffer, int offset, int len)
Ghi một dãy byte vào stream. Bắt đầu ghi từ byte thứ offset, và ghi tổng cộng len byte.
abstract void write(int b)
Ghi một byte vào stream.
Đây là phương thức trừu tượng.
Các phương thức cơ bản của các byte stream tổng quát
Lưu ý: Các phương thức đọc/ghi sẽ phát sinh IOException nếu có lỗi xảy ra.

1.2.2       Các luồng đọc byte hiện thực

Để sử đọc/ghi luồng dữ liệu dạng byte, các lớp con hiện thực của InputStreamOutputStreamthường được sử dụng gồm:
§  FileInputStream: đọc (các) byte từ tập tin.
§  FileOutputStream: ghi (các) byte vào tập tin.
§  ByteArrayInputStream: chứa bộ đệm là mảng byte để đọc dữ liệu.
§  ByteArrayOutputStream: chứa bộ đệm là mảng byte để ghi dữ liệu.
§  PipedInputStream: đọc (các) byte từ một piped output stream.
§  PipedOutputStream: ghi (các) byte vào một piped input stream.
Nhìn chung các lớp này đều có những chức năng chính tương tự như nhau. Dưới đây chỉ trình bày những phương thức đặc thù của chúng.
Stream
Phương thức
Ý nghĩa
File
Input
Stream
FileInputStream(File file)
Tạo FileInputStream để đọc dữ liệu từ một tập tin liên kết tới đối tượng File.
FileInputStream(String name)
Tạo FileInputStream để đọc dữ liệu từ một tập tin có tên là name.
File
Output
Stream
FileOutputStream(File file)
Tạo FileOutputStream để ghi dữ liệu vào một tập tin liên kết tới đối tượng File.
FileOutputStream(File file, boolean append)
Tạo FileOutputStream để ghi dữ liệu tập tin liên kết tới đối tượng File.
Nếu appendtrue thì sẽ ghi tiếp vào cuối tập tin, ngược lại thì ghi đè lên tập tin.
FileOutputStream(String name)
Tạo FileOutputStream để ghi dữ liệu vào một tập tin có tên là name.
FileOutputStream(String name, boolean append)
Tạo FileOutputStream để ghi dữ liệu vào một tập tin có tên là name.
Nếu appendtrue thì sẽ ghi tiếp vào cuối tập tin, ngược lại thì ghi đè lên tập tin.
Byte
Array
Input
Stream
ByteArrayInputStream(byte[] buf)
Tạo ra ByteArrayInputStream và dùng buf để làm vùng đệm.
ByteArrayInputStream(byte[] buf, int off, int len)
Tạo ra ByteArrayInputStream và dùng một phần của buf để làm vùng đệm.
Byte
Array
Output
Stream
ByteArrayOutputStream()
Tạo ra một ByteArrayOutputStream với vùng đệm 32 byte và có thể tăng nếu cần.
ByteArrayOutputStream(int size)
Tạo ra một ByteArrayOutputStream với vùng đệm size byte.
byte[]toByteArray()
Tạo ra mảng byte là bản sao của vùng đệm của this.
String toString()
Tạo ra chuỗi là bản sao của vùng đệm của this với các byte được đổi thành ký tự tương ứng.
void writeTo(OutputStream out)
Ghi dữ liệu trong vùng đệm vào một output stream khác.
Piped
Input
Stream
PipedInputStream()
Tạo ra một piped input stream. Stream này chưa được kết nối với piped output stream nào.
PipedInputStream
(PipedOutputStream src)
Tạo ra một piped input stream kết nối với piped output stream src.
connect(PipedOutputStream src)
Kết nối tới piped output stream src.
Piped
Output
Stream
PipedOutputStream()
Tạo ra một piped output stream. Stream này chưa được kết nối với piped input stream nào.
PipedOutputStream
(PipedInputStream snk)
Tạo ra một piped output stream kết nối với piped input stream snk.
connect(PipedInputStream snk)
Kết nối tới piped input stream snk.
Bảng 8: Những phương thức đặc trưng của các byte stream cụ thể

1.2.3       Các ví dụ

Để dùng các stream, trước hết cần import package java.io.
importjava.io.*;
Dưới đây sẽ trình bày các ví dụ về file stream và piped stream.
File stream:
String fileName="C:\\TestB.txt";
// Phát sinh và xuất mảng ngẫu nhiên
byte[]a=new byte[10];
System.out.print("Du lieu phat sinh: ");
for(inti=0;i<a.length;i++)
{         
     a[i]=(byte)Math.round(Math.random()*20);
     System.out.print(a[i]+" ");
}
System.out.println();
// Ghi mảng a vào tập tin
FileOutputStream fo=newFileOutputStream(fileName);
fo.write(a);
fo.close();
    
// Đọc tập tin vào mảng b
FileInputStream  fi=newFileInputStream (fileName);       
byte[]b=new byte[fi.available()];
fi.read(b);
fi.close();
// Xuất mảng b
System.out.print("Du lieu doc duoc : ");
for(inti=0;i<b.length;i++)
{
     System.out.print(b[i]+" ");
}
System.out.println();
Kết quả thực thi (các con số sẽ khác nhau với mỗi lần chạy):
Du lieu phat sinh: 4 14 0 16 2 19 10 9 9 15
Du lieu doc duoc : 4 14 0 16 2 19 10 9 9 15
Press any key to continue...
Ví dụ về luồng mảng: Tạo một mảng gồm 100 byte rồi gắn vào mảng này một luồng ByteArrayInputStream để lấy dữ liệu ra.
import java.io.*;
public class LuongNhapMang
{
     public static void main(String[] args)
     {
     byte[] b = new byte[100];
     for(byte i=0;i<b.length;i++) b[i]=i;
     try{
           InputStream is = new ByteArrayInputStream(b);
           for(byte i=0;i<b.length;i++)
                System.out.print(is.read()+" ");
     }
     catch(IOException e)
     {
           System.err.println(e);
     }
     }
}
Kết quả thực hiện chương trình
C:\MyJava\Baitap>java LuongNhapMang
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
Ví dụ luồng viết mảng: Viết chương trình tạo lập một luồng xuất mảng (ByteArrayOutputStream) 100 byte. Ghi vào luồng xuất mảng 100 phần tử từ 0 đến 99. Đổ dữ liệu từ luồng xuất mảng vào mảng b. In dữ liệu từ mảng b ra màn hình.
import java.io.*;
class LuongXuatMang
{
     public static void main(String[] args)
     {
           try{
       //Tao mot luong xuat mang 100 byte
       ByteArrayOutputStream os = new ByteArrayOutputStream(100);
       //Ghi du lieu vao luong
       for(byte i=0;i<100;i++) os.write(i);
       //Doc du lieu tu luong vao mang
       byte[] b = os.toByteArray();
      for(byte i=0;i<100;i++) System.out.print(b[i]+" ");
      os.close();
     }catch(IOException e)
     {
       System.err.println(e);
     }
  }
}
Kết quả thực hiện chương trình:
C:\MyJava\Baitap>java LuongXuatMang
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
Ví dụ về Piped stream:
PipedInputStream  pi= newPipedInputStream();
PipedOutputStream po= newPipedOutputStream(pi);

// Ghi các số nguyên ngẫu nhiên bằng PipedOutputStream
System.out.print("Du lieu ghi duoc: ");
for(int i=0;i<10;i++)
{         
     int b=(int)Math.round(Math.random()*20);
     po.write(b);
     System.out.print(b+" ");
}
po.flush();
System.out.println();

// Đọc các số nguyên từ PipedOutputStream bằng PipedInputStream
System.out.print("Du lieu doc duoc: ");
while(pi.available()>0)
{
     int b=pi.read();
     System.out.print(b+" ");
}
System.out.println();

// Đóng các stream
pi.close();
po.close();
Kết quả thực thi (các con số sẽ khác nhau với mỗi lần chạy):
Du lieu ghi duoc: 16 19 9 11 19 3 2 13 18 16
Du lieu doc duoc: 16 19 9 11 19 3 2 13 18 16
Press any key to continue...

1.3             Các luồng ký tự

            Các luồng ký tự (character stream) có chức năng đọc hoặc ghi dữ liệu dạng ký tự. Dựa vào thao tác, các character stream được chia ra hai loại chính: nhóm input được đại diện bởi lớp Readervà nhóm output được đại diện bởi Writer. Các lớp xử lý trên character stream đều được kế thừa từ hai lớp này.

Hình 2: Sơ đồ tổ chức của các stream đọc ký tự

Hình 3: Sơ đồ tổ chức của các stream ghi ký tự

1.3.1       Các luồng ký tự tổng quát

            Gồm các lớp ReaderWriter. Đây hai là lớp trừu tượng, nó quy định các phương thức đọc và ghi dữ liệu dạng character và một số phương thức hỗ trợ khác:
Phương thức
Ý nghĩa
Lớp Reader
void close()
Đóng stream.
void mark(int readlimit)
Đánh dấu vị trí hiện tại. Nếu sau khi đánh dấu ta đọc quá readlimit ký tự thì chỗ đánh dấu không còn hiệu lực.
boolean markSupported()
Trả về true nếu stream hỗ trợ markreset.
abstract int read()
Đọc ký tự kế tiếp trong stream.
Quy ước: Trả về -1 nếu hết stream.
Đây là phương thức trừu tượng.
int read(char[]cbuf)
Đọc một dãy ký tự và lưu kết quả trong mảng cbuf.
Sau khi đọc xong sẽ trả về số ký tự đọc được thật sự (nếu đang đọc mà hết stream thì số ký tự đọc được thật sự sẽ nhỏ hơn sức chứa của cbuf).
Nếu stream đã hết mà vẫn đọc nữa thì kết quả trả về là -1.
int read(char[]cbuf, int offset, int len)
Đọc một dãy ký tự và lưu kết quả trong mảng cbuf kể tự ký tự thứ offset.
Sau khi đọc xong sẽ trả về số ký tự đọc được thật sự (nếu đang đọc mà hết stream thì số ký tự đọc được thật sự sẽ nhỏ hơn len).
Nếu stream đã hết mà vẫn đọc nữa thì kết quả trả về là -1.
void read(CharBuffer target)
Đọc một dãy ký tự và lưu kết quả trong target.
boolean ready()
Trả về true nếu stream sẵn sàng để đọc.
void reset()
Trở lại chỗ đã đánh dấu bằng phương thức mark().
long skip(long n)
Bỏ qua n ký tự (để đọc các ký tự tiếp sau).
Lớp Writer
Writer append(char c)
Nối đuôi ký tự c vào stream.
Writer append(CharSequence csq)
Nối đuôi dãy ký tự csq vào stream.
Writer append(CharSequence csq, int start, int end)
Nối đuôi một phần của dãy ký tự csq vào stream.


void close()
Đóng stream.
void flush()
Buộc stream ghi hết dữ liệu trong vùng đệm ra ngoài.
void write(char[]cbuf)
Ghi một mảng ký tự vào stream. Số ký tự được ghi sẽ là cbuffer.length.
abstract void write(int c)
Ghi một ký tự vào stream.
Đây là phương thức trừu tượng.
void write(String c)
Ghi một chuỗi vào stream.
void write(String str, int off, int len)
Ghi một phần của chuỗi vào stream.
Các phương thức cơ bản của character stream tổng quát
Lưu ý: Các phương thức đọc/ghi sẽ phát sinh IOException nếu có lỗi xảy ra.

1.3.2       Các luồng ký tự hiện thực

Để sử đọc/ghi ký tự, ta phải dùng các lớp con của ReaderWriter. Các lớp thường dùng gồm:
§  FileReader: đọc (các) ký tự từ tập tin.
§  FileWriter: ghi (các) ký tự vào tập tin.
§  CharArrayReader: chứa bộ đệm là mảng ký tự để đọc dữ liệu.
§  CharArrayWriter: chứa bộ đệm là mảng ký tự để ghi dữ liệu.
§  PipedReader: đọc (các) ký tự từ một piped writer.
§  PipedWriter: ghi (các) ký tự vào một piped reader.
§  StringReader: đọc chuỗi ký tự.
§  StringWriter: ghi chuỗi ký tự.
Nhìn chung các lớp này đều có những chức năng chính tương tự như nhau. Dưới đây chỉ trình bày những phương thức đặc thù của chúng.
Stream
Phương thức
Ý nghĩa
File
Reader
FileReader(File file)
Tạo FileReader để đọc dữ liệu từ một tập tin liên kết tới đối tượng File.
FileReader(String name)
Tạo FileReader để đọc dữ liệu từ một tập tin có tên là name.
File
Writer
FileWriter (File file)
Tạo FileWriter để ghi dữ liệu vào một tập tin liên kết tới đối tượng File.
FileWriter(File file, boolean append)
Tạo FileWriter để ghi dữ liệu tập tin liên kết tới đối tượng File.
Nếu appendtrue thì sẽ ghi tiếp vào cuối tập tin, ngược lại thì ghi đè lên tập tin.
FileWriter(String name)
Tạo FileWriter để ghi dữ liệu vào một tập tin có tên là name.
FileWriter(String name, boolean append)
Tạo FileWriter để ghi dữ liệu vào một tập tin có tên là name.
Nếu appendtrue thì sẽ ghi tiếp vào cuối tập tin, ngược lại thì ghi đè lên tập tin.
Char
Array
Reader
CharArrayReader(char[] buf)
Tạo ra CharArrayReader và dùng buf để làm vùng đệm.
CharArrayReader(char[] buf, int off, int len)
Tạo ra CharArrayReader và dùng một phần của buf để làm vùng đệm.
Char
Array
Writer
CharArrayWriter()
Tạo ra một CharArrayWriter.
CharArrayWriter(int size)
Tạo ra một CharArrayWriter với vùng đệm size ký tự.
char[]toCharArray()
Tạo ra mảng ký tự là bản sao của vùng đệm của this.
String toString()
Tạo ra chuỗi là bản sao của vùng đệm của this với các byte được đổi thành ký tự tương ứng.
void writeTo(Writer out)
Ghi dữ liệu trong vùng đệm vào một writer khác.
Piped
Reader
PipedReader()
Tạo ra một piped reader. Stream này chưa được kết nối với piped output stream nào.
PipedReader
(PipedWriter src)
Tạo ra một piped reader kết nối với piped output stream src.
connect(PipedWriter src)
Kết nối tới piped writer src.
Piped
Writer
PipedWriter()
Tạo ra một piped writer. Stream này chưa được kết nối với piped input stream nào.
PipedWriter
(PipedReader snk)
Tạo ra một piped writer kết nối với piped reader snk.
connect(PipedReader snk)
Kết nối tới piped reader snk.
String
Reader
StringReader(String s)
Tạo ra một StringReader.
String
Writer
StringWriter()
Tạo ra một StringReader, dùng vùng đệm có kích thước mặc định.
StringWriter(int initialSize)
Tạo ra một StringReader, dùng vùng đệm có kích thước là initialSize.
StringBuffer getBuffer()
Trả về vùng đệm của stream.
Bảng 9: Những phương thức đặc trưng của các character stream cụ thể

1.3.3       Các ví dụ

Dùng file reader và file writer:
String fileName="C:\\TestC.txt";
String s="Hello File Reader/Writer!";
System.out.println("Du lieu ban dau  : "+s);
// Ghi s vào tập tin
FileWriter fw=newFileWriter(fileName);
fw.write(s);
fw.close();
// Đọc tâp tin vào chuỗi sb
FileReader  fr=newFileReader(fileName);       
StringBuffer sb=newStringBuffer();
charca[]=new char[5];          // Đọc mỗi lần tối đa 5 ký tự
while(fr.ready())
{
     int len=fr.read(ca);       // len: số ký tự đọc được thật sự
     sb.append(ca,0,len);      
}
fr.close();
// Xuất chuỗi sb
System.out.println("Du lieu doc duoc : "+sb);
Kết quả thực thi:
Du lieu ban dau  : Hello File Reader/Writer!
Du lieu doc duoc : Hello File Reader/Writer!
Press any key to continue...
Dùng piped reader và piped writer:
PipedReader pr=newPipedReader();
PipedWriter pw=newPipedWriter(pr);
// PipedWriter gởi dữ liệu
String s="Hello Piped Reader/Writer!";
System.out.println("Du lieu ghi     : "+s);
pw.write(s);        
pw.close();

// PipedReader nhận dữ liệu
StringBuffer sb=newStringBuffer();
charca[]=new char[5];          // Đọc mỗi lần tối đa 5 ký tự
while(pr.ready())
{
     int len=pr.read(ca);       // len: số ký tự đọc được thật sự
     sb.append(ca,0,len);      
}
pr.close();
// Kết quả
System.out.println("Du lieu doc duoc: "+sb);
Kết quả thực thi:
Du lieu ghi     : Hello Piped Reader/Writer!
Du lieu doc duoc: Hello Piped Reader/Writer!
Press any key to continue...

1.4             Các luồng lọc dữ liệu (Filter Stream)

            Bởi vì các luồng dữ liệu được chuyển tải dạng byte hoặc ký tự, nên cần có một bộ biến đổi các luồng dữ liệu này sang những giá trị có định kiểu khác nhau. Java cung cấp thêm các luồng lọc dữ liệu. Khi các luồng này được tạo ra, nó phải được gắn với một luồng dữ liệu cụ thể để lọc nó. Do vậy, việc đọc dữ liệu từ một nguồn là sự phối hợp giữa các luồng tạo thành một dây chuyền xử lý trên các luồng khi có thao tác đọc/ghi xảy ra.
·            Dây chuyền đọc bắt đầu bởi một luồng đọc cơ bản và kết thúc bởi một luồng lọc dữ liệu. Ở giữa có thể có thểm các luồng xử lý đọc trung gian.
·            Dây chuyền ghi bắt đầu bởi một luồng xử lý ghi và kết thúc bởi một luồng ghi cơ bản. Ở giữa có thể có các luồng xử lý ghi trung gian.
Ví dụ:

Ví dụ về dây chuyền đọc/ghi dữ liệu

1.4.1       Các luồng lọc tổng quát

Trong Java, các luồng xử lý lọc tổng quát là các lớp trừu tượng sau:
·            FilerInputStream: luồng xử lý cho thao tác đọc dữ liệu dạng byte.
·            FilerOutputStream: luồng xử lý cho thao tác ghi dữ liệu dạng byte.
·            FilerReader: luồng xử lý cho thao tác đọc dữ liệu dạng ký tự.
·            FilerWriter: luồng xử lý cho thao tác ghi dữ liệu dạng ký tự.

1.4.2       Các luồng lọc hiện thực

            Các luồng lọc hiện thực các luồng lọc tổng quát chịu trách nhiệm hiện thực các thao tác biến đổi dữ liệu có định kiểu thành luồng byte/ký tự hoặc ngược lại từ luồng byte/ký tự thành giá trị có định kiểu.      Cụ thể, các luồng lọc này là DataInputStream, DataOutputStream. Các lớp này có những phương thức đặc trưng như sau:
Stream
Phương thức
Ý nghĩa
Data
Input
Stream
DataInputStream
(InputStream in)
Tạo stream để đọc dữ liệu theo định dạng.
boolean readBoolean()
Đọc một giá trị kiểu boolean.
Các kiểu byte, char, double, float,... cũng có những phương thức tương ứng.
Data
Output
Stream
DataOutputStream
(OutputStream out)
Tạo stream để ghi dữ liệu theo định dạng.
int size()
Trả về số byte mà stream đã ghi.
void writeBoolean
(
boolean v)
Ghi một biến kiểu boolean.
Các kiểu byte, char, double, float,... cũng có những phương thức tương ứng.
void writeBytes(String s)
Ghi chuỗi thành một dãy các byte.
void writeChars(String s)
Ghi chuỗi thành một dãy các ký tự.
Lưu ý:
·            Khi đọc các biến, phải đọc đúng theo thứ tự đã ghi.
·            Để ghi chuỗi hoặc các đối tượng khác, ta phải dùng chức năng đọc/ghi object.
·            Ta có thể kết hợp đọc có định dạng với vùng đệm.
Ví dụ: đọc/ghi các biến trên tập tin
String name="C:\\TestD.txt";
// Ghi dữ liệu
DataOutputStream fo=newDataOutputStream(new FileOutputStream(name));
fo.writeBoolean(true);         
fo.writeInt(786);         
fo.writeFloat(0.123f);         
fo.close();
// Đọc dữ liệu
DataInputStream  fi=newDataInputStream(new FileInputStream (name));
booleanb=fi.readBoolean();
inti=fi.readInt();
floatf=fi.readFloat();
fo.close();
// Xuất dữ liệu đọc được ra màn hình
System.out.println("Du lieu doc duoc: ");
System.out.println(String.valueOf(b));
System.out.println(i);
System.out.println(String.valueOf(f));
Kết quả thực thi:
Du lieu doc duoc:
true
786
0.123
Press any key to continue...

1.5             Các luồng đệm dữ liệu

            Để tăng tốc độ đọc/ghi, nhất là đối với thao tác đọc/ghi trên bộ nhớ phụ, người ta dùng kỹ thuật vùng nhớ đệm.
·            Vùng đệm đọc: dữ liệu sẽ được đọc vào vùng đệm thành từng khối, sau đó lấy ra dùng từ từ, khối hết thì sẽ đọc tiếp khối kế à giảm số thao tác đọc.
·            Vùng đệm ghi: dữ liệu cần ghi sẽ được gom lại đến khi đủ số lượng cần thiết thì sẽ được ghi một lần à giảm số thao tác ghi.
            Như vậy, vùng đệm càng lớn thì càng tăng tốc độ, nhưng sẽ càng dễ xảy ra mất dữ liệu khi chương trình bị chấm dứt đột ngột. Ví dụ: ta yêu cầu ghi nhưng do chưa đủ dữ liệu nên chương trình chưa ghi thật sự vào đĩa, sau đó bị cúp điện àcác dữ liệu được ta yêu cầu ghi đó sẽ mất.
Trong Java, các lớp luồng đệm hỗ trợ  thao tác đọc/ghi như:
·            BufferedInputStream: đọc dữ liệu dạng byte, có dùng vùng đệm
·            BufferedOutputStream: ghi dữ liệu dạng byte, có dùng vùng đệm
·            BufferedReader: đọc dữ liệu dạng ký tự, có dùng vùng đệm
·            BufferedWriter: ghi dữ liệu dạng ký tự, có dùng vùng đệm
            Khi tạo ra một đối tượng luồng đệm, nó phải gắn với một đối tượng luồng dữ liệu khác. Nhìn chung các luồng đệm có những phương thức giống như luồng thông thường, nhưng có khác biệt về cách khởi tạo:
Stream
Phương thức
Ý nghĩa
Buffered
Input
Stream
BufferedInputStream
(InputStream in)
Tạo một stream vùng đệm để đọc dữ liệu dạng byte.
BufferedInputStream
(InputStream in,
int size)
Tạo một stream với vùng đệm kích thước size để để đọc dữ liệu dạng byte.
Buffered
Output
Stream
BufferedOutputStream
(OutputStream out)
Tạo một stream vùng đệm để ghi dữ liệu dạng byte.
BufferedOutputStream
(OutputStream out,
int sz)
Tạo một stream với vùng đệm kích thước sz byte để để ghi dữ liệu dạng byte.
Buffered
Reader
BufferedReader(Reader in)
Tạo một stream vùng đệm để đọc dữ liệu dạng ký tự.
BufferedReader
(Reader in,
int sz)
Tạo một stream với vùng đệm kích thước sz để để đọc dữ liệu dạng ký tự.
Buffered
Writer
BufferedWriter(Writer out)
Tạo một stream vùng đệm để ghi dữ liệu dạng ký tự.
BufferedWriter
(Writer out,
int sz)
Tạo một stream với vùng đệm kích thước sz byte để để ghi dữ liệu dạng byte.
void newLine()
Ghi ký tự xuống dòng vào stream.
Bảng 10: Những phương thức đặc trưng của các stream vùng đệm
Ví dụ:
String fileName="C:\\TestC.txt";
String s="Hello Buffered File Reader/Writer!";
System.out.println("Du lieu ban dau  : "+s);

// Ghi s vào tập tin
BufferedWriter bw=newBufferedWriter(new FileWriter(fileName));
bw.write(s);
bw.close();

// Đọc tâp tin vào chuỗi sb
BufferedReader br=newBufferedReader(new FileReader(fileName));
StringBuffer sb=newStringBuffer();
charca[]=new char[5];               // Đọc mỗi lần tối đa 5 ký tự
while(br.ready())
{
     int len=br.read(ca);       // len: số ký tự đọc được thật sự
     sb.append(ca,0,len);      
}
br.close();

// Xuất chuỗi sb
System.out.println("Du lieu doc duoc : "+sb);
Kết quả:
Du lieu ban dau  : Hello Buffered File Reader/Writer!
Du lieu doc duoc : Hello Buffered File Reader/Writer!
Press any key to continue...
Nhìn vào ví dụ trên, ta thấy dùng stream vùng đệm và không dùng  cho kết quả không khác gì nhau. Vậy đâu là ưu điểm của stream vùng đệm? Hãy xem ví dụ kế tiếp.
Ví dụ: dưới đây là ví dụ so sánh tốc độ khi dùng và không dùng stream vùng đệm:
String fileName="C:\\TestB.txt";
longn=50000;
// Ghi với stream vùng đệm
{
     long t=System.currentTimeMillis();

     FileOutputStream fo=newFileOutputStream(fileName);
     BufferedOutputStream bo=newBufferedOutputStream(fo);
     for(inti=0;i<n;i++)      
           bo.write(i);        
     bo.close();

     t=System.currentTimeMillis()-t;
     System.out.println("Ghi co vung dem   : mat "+t+"ms.");
}
// Ghi không có stream vùng đệm
{
     long t=System.currentTimeMillis();

     FileOutputStream fo=newFileOutputStream(fileName);
     for(inti=0;i<n;i++)
           fo.write(i);
     fo.close();

     t=System.currentTimeMillis()-t;
     System.out.println("Ghi khong vung dem: mat "+t+"ms.");
}
Kết quả thực thi: thời gian chạy rất chênh lệch (kết quả có thể khác nhau tùy máy)
Ghi co vung dem   : mat 15ms.
Ghi khong vung dem: mat 1703ms.
Press any key to continue...
Ví dụ: kết hợp đọc/ghi có định dạng trên tập tin, có dùng vùng đệm
String fileName="C:\\TestB.txt";
// Ghi các số từ 0 tới 9 và căn bậc 2 tương ứng của chúng
// Tạo các stream
FileOutputStream fo=newFileOutputStream(fileName);
BufferedOutputStream bo=newBufferedOutputStream(fo);
DataOutputStream dos=newDataOutputStream(bo);
// Ghi các số
for(inti=0;i<10;i++)
{         
     dos.writeInt(i);
     dos.writeDouble(Math.sqrt(i));
}
dos.close();
/* Đọc các số nguyên và căn bậc hai tương ứng */
// Tạo các stream
FileInputStream fi=newFileInputStream(fileName);
BufferedInputStream bi=newBufferedInputStream(fi);
DataInputStream dis=newDataInputStream(bi);
// Đọc các số và xuất ra màn hình
while(dis.available()>0)
{
     int i=dis.readInt();
     double sinI=dis.readDouble();
     System.out.println("sqrt("+i+")"+" = "+sinI);
}
dis.close();
Kết quả thực thi:
sqrt(0) = 0.0
sqrt(1) = 1.0
sqrt(2) = 1.4142135623730951
sqrt(3) = 1.7320508075688772
sqrt(4) = 2.0
sqrt(5) = 2.23606797749979
sqrt(6) = 2.449489742783178
sqrt(7) = 2.6457513110645907
sqrt(8) = 2.8284271247461903
sqrt(9) = 3.0
Press any key to continue...

1.6             Các lớp định dạng luồng dữ liệu nhập/xuất

Java hỗ trợ hai lớp đối tượng Scanner (thuộc gói java.util.*) và PrintWriter (thuộc gói java.io.*) rất hiệu quả cho việc định dạng dữ liệu của một luồng nhập/xuất. Bảng đưới đây trình bày một số phương phức thông dụng của hai lớp đối tượng này.
Phương thức
Ý nghĩa
Lớp Scanner
Scanner(InputStream source)
Khởi tạo đối tượng Scanner lấy dữ liệu từ một luồng nhập.
Scanner(ReadableByteChannel  source)
Khởi tạo đối tượng Scanner lấy dữ liệu từ một kênh nhập.
void close()
Đóng đối tượng Scanner.
bool nextBoolean()
Đọc một khối dữ liệu trong luồng và ép nó sang kiểu logic bool.
int nextInt()
Đọc một khối dữ liệu trong luồng và ép nó sang kiểu số nguyên int.
long nextLong()
Đọc một khối dữ liệu trong luồng và ép nó sang kiểu số nguyên long.
float nextFloat()
Đọc một khối dữ liệu trong luồng và ép nó sang kiểu số thực float.
double nextDouble()
Đọc một khối dữ liệu trong luồng và ép nó sang kiểu số thực double.
String nextLine()
Đọc các khối dữ liệu trong luồng và ép nó sang kiểu chuỗi String.
bool hasNext()
kiểm tra luồng còn khối dữ liệu nào không.
Lớp PrintWriter
PrintWriter(OutputStream out)
Khởi tạo đối tượng PrintWriter để viết dữ liệu ra luồng xuất byte out.
PrintWriter(Writer out)
Khởi tạo đối tượng PrintWriter để viết dữ liệu ra luồng xuất ký tự out.
void close()
Đóng đối tượng PrintWriter.
void print(String s)
Ghi một chuỗi ra luồng.
void print(bool b)
Ghi giá trị bool ra luồng.
void println()
Ghi ký hiệu kết thúc dòng ra luồng
void println(int i)
Ghi một số nguyên i và ký hiệu kết thúc dòng ra luồng.
void println(String s)
Ghi một chuỗi s và ký hiệu kết thúc dòng ra luồng.
void flush()
Ghi toàn bộ dữ liệu trong PrintWriter ra luồng.
 Ví dụ: Đọc và ghi dữ liệu có định dạng từ hai luồng nhập xuất cơ bản System.in và System.out
import java.util.*;
import java.io.*;
public class NhapXuat {
    public static void main(String[] args) {
    //hien thi day so vua nhap len man hinh su dung PrintWriter
     PrintWriter pw=new PrintWriter(System.out);
    //Tao doi tuong Scanner de dinh dang du lieu cho luong
     //nhap ban phim
     Scanner sc=new Scanner(System.in);         
     //doc so luong phan tu day so can nhap
     pw.println("nhap so phan tu n:"); pw.flush();
     int n =sc.nextInt();
     //doc vao mot day so n nguyen luu vao mang     
     int a[] =new int[n];
     for(int i=0;i<n;i++){
         pw.println("a[" + i+"]=");pw.flush();
         a[i]=sc.nextInt();
     }                     
     pw.println("Hien thi day so su dung doi tuong Printer");
     for(int i=0;i<n;i++)
           pw.print(a[i]);
     pw.close();        
    }
}
Kết quả thực hiện
nhap so phan tu n:
3
a[0]=1
a[1]=2
a[2]=3
Hien thi day so su dung doi tuong Printer
1
2
3

1.7             Tuần tự hóa đối tượng (object serialization)

            Object serialization là khả năng biến đổi một đối tượng thành một dãy byte để lưu trữ trên bộ nhớ phụ hoặc truyền đi nơi khác. Trong Java, object serialization đã được tự động hóa hoàn toàn và hầu như lập trình viên không phải làm gì thêm.
Để một đối tượng có thể được "serialize", ta chỉ cần cho nó implement interface Serializable. Mọi việc sau đó như đọc/ghi/truyền/nhận đều do Java thực hiện.
Lưu ý:
·            Chỉ có các thuộc tính (dữ liệu) của đối tượng mới được serialize.
·            Các thuộc tính được đánh dấu bằng từ khóa transient (nghĩa là có tính tạm thời) sẽ không được serialize.
·            Sau khi serialize, trạng thái của đối tượng được lưu trữ trên bộ nhớ ngoài được gọi là persistence (nghĩa là được giữ lại một cách bền vững).
Ví dụ: tạo ra lớp học sinh có thể được serialize:
public class HocSinh implements Serializable
{
     protected String hoTen;
     protected int namSinh;
     protected float diemVan, diemToan;
     protected transientfloat diemTrungBinh;
     // ...
}

1.8             Luồng viết đối tượng

Trong Java, các lớp đảm nhận việc đọc/ghi đối tượng gồm:
·            ObjectInputStream: đọc dãy byte và chuyển thành đối tượng phù hợp.
·            ObjectOutputStream: chuyển đối tượng thành dãy byte và ghi.
Các đối tượng đọc/ghi này cũng không thể hoạt động độc lập mà phải được liên kết với stream khác. Chúng có các phương thức chính như sau:
Stream
Phương thức
Ý nghĩa
Object
Input
Stream
ObjectInputStream
(InputStream in)
Tạo stream để đọc đối tượng.
Object readObject()
Đọc một đối tượng.Nếu đối tượng không được khai báo trong chương trình thì sẽ phát sinh ClassNotFoundException.
Object
Output
Stream
ObjectOutputStream
(OutputStream out)
Tạo stream để ghi đối tượng.
void reset()
Phục hồi lại stream và hủy bỏ thông tin về các đối tượng mà stream đã ghi.
writeObject(Object obj)
Ghi một đối tượng.
Bảng 11: Những thao tác đặc trưng của các object stream
Tạo ra lớp phân số có thể được serialize:
public class PhanSo implements Serializable
{
     protected int tu,mau;
     private transient float val=0; 
     publicPhanSo()
     {
           tu=0;
           mau=1;
     }
     publicPhanSo(inttu, intmau)
     {
           this.tu=tu;
           this.mau=mau;
           val=(float)tu/mau;
     }   
     public String toString()
     {
           return tu+"/"+mau+" ("+val+")";
     }
}
Ghi và đọc các đối tượng phân số (có dùng stream vùng đệm):
// Ghi dữ liệu
FileOutputStream fo=newFileOutputStream("C:\\TestO.bin");
BufferedOutputStream bo=newBufferedOutputStream(fo);
ObjectOutputStream oo=newObjectOutputStream(bo);

System.out.println("Du lieu ghi duoc:");
for(inti=0;i<4;i++)
{         
     int tu =(int)(Math.random()*10);
     intmau=(int)(Math.random()*9)+1;
     PhanSo ps=newPhanSo(tu,mau);
     oo.writeObject(ps);            
     System.out.println(ps);
}         
oo.close();         

// Đọc dữ liệu
FileInputStream fi=newFileInputStream("C:\\TestO.bin");
BufferedInputStream bi=newBufferedInputStream(fi);
ObjectInputStream oi=newObjectInputStream(bi);

System.out.println("\nDu lieu doc duoc:");
while(bi.available()>0)
{
     PhanSo ps=(PhanSo)oi.readObject();
     System.out.println(ps);
}
oi.close();
Kết quả thực thi có dạng như sau (kết quả thực tế sẽ khác nhau với mỗi lần chạy):
Du lieu ghi duoc:
2/2 (1.0)
6/8 (0.75)
5/6 (0.8333333)
3/5 (0.6)

Du lieu doc duoc:
2/2 (0.0)
6/8 (0.0)
5/6 (0.0)
3/5 (0.0)
Press any key to continue...
Ta thấy thuộc tính valkhông được ghi do nó là transient. Nếu trong lớp phân số, ta bỏ từ khóa transient thì kết quả sẽ có dạng như sau:
Du lieu ghi duoc:
2/6 (0.33333334)
3/7 (0.42857143)
2/1 (2.0)
2/4 (0.5)

Du lieu doc duoc:
2/6 (0.33333334)
3/7 (0.42857143)
2/1 (2.0)
2/4 (0.5)
Press any key to continue...

1.9             Bài tập           

1.                  Viết chương trình cài đặt tất cả các ví dụ chong chương.

2.                  Cho biết các loại lớp biểu diễn luồng dữ liệu trong Java. Nêu tính năng chính của từng loại.