Nguyễn Đức Hiển – Bài giảng Lập trình Java
1
Java Object-Oriented Programming
Giảng viên : Nguyễn Đức Hiển
Email :
Website :
Thời lượng
Lý thuyết : 2 tín chỉ (30 tiết)
Thực hành + thảo luận : 1 tín chỉ
Nguyễn Đức Hiển – Bài giảng Lập trình Java
2
Chương 5
Các dòng nhập/xuất
(Input/Output Streams)
Nguyễn Đức Hiển – Bài giảng Lập trình Java
3
Nội dung
Khái niệm
Dòng bộ đệm
Nhập/xuất với tập tin
Tuần tự hóa
Nguyễn Đức Hiển – Bài giảng Lập trình Java
4
Giới thiệu
Dòng (stream) là một sự biểu diễn trừu tượng dữ liệu
được kết nối với một số thiết bị vào hay ra
Nguyễn Đức Hiển – Bài giảng Lập trình Java
5
Java Stream
Hỗ trợ sẵn bộ đệm tự động (buffering)
Hỗ trợ sự biểu diễn của các dòng sử dụng sự trừu
tượng hóa mức cao (khác với bytes)
Đọc/ghi các kiểu dữ liệu đơn nguyên
Đọc/ghi các đối tượng
Định dạng sẵn các dòng ký tự bao gồm sự chuyển đổi qua
lại với các biểu diễn khác (như int, double,…)
Nguyễn Đức Hiển – Bài giảng Lập trình Java
6
Các lớp stream cơ bản
Các lớp stream chính ở trong gói java.io.*
Hai lớp trừu tượng chính
InputStream
int read()
int read(byte[] b)
int read(byte[] b, int off, int len)
OutputStream
void write(int b)
void write(byte[] b)
void write(byte[] b, int off, int len)
Cung cấp chức năng cơ bản cho việc đọc dữ liệu
đến một luồng theo dạng các byte thô
Nguyễn Đức Hiển – Bài giảng Lập trình Java
7
InputStream và OutputStream
Nhiều lớp dẫn xuất tồn tại để cung cấp các chức
năng chuyên dụng.
Các lớp dẫn xuất đáng chú ý:
FileInputStream, FileOutputStream
BufferedInputStream, BufferedOutputStream
ObjectInputStream, ObjectOutputStream
PrintStream
Và còn nhiều hơn
Nguyễn Đức Hiển – Bài giảng Lập trình Java
8
Ví dụ: FileInputStream
Ví dụ chương trình đọc dữ liệu từ một tập tin theo
từng byte (đọc một byte tại một thời điểm).
Nguyễn Đức Hiển – Bài giảng Lập trình Java
9
Các dòng bộ đệm
Ví dụ trước không có hiệu quả bởi vì nó đọc trực tiếp
từ file một byte tại một thời điểm chậm
Chúng ta có thể dùng lớp BufferedInputStream bao
bọc lớp FileInputStream để đọc khối dữ liệu lớn hơn
và lưu giữ trong một bộ đệm sử dụng cho việc đọc.
Nguyễn Đức Hiển – Bài giảng Lập trình Java
10
Các dòng bộ đệm
File
FileInputStream
BufferedInputStream
Java Program
{
…
…
}
BufferedInputStream đọc dữ
liệu từ file trong các khối lớn
và lưu giữ dữ liệu trong một
bộ đệm bên trong
Bộ đệm
Sau đó, bạn có thể đọc dữ liệu
từ BufferedInputStream và dữ
liệu được đọc từ bộ đệm thay vì
trực tiếp từ file trên mỗi lần đọc
Nguyễn Đức Hiển – Bài giảng Lập trình Java
11
Ví dụ: BufferedInputStream
Ví dụ sử dụng lớp BufferedInputStream bao bọc lớp
FileInputStream để đọc dữ liệu từ file:
Nguyễn Đức Hiển – Bài giảng Lập trình Java
12
Các dòng ký tự
Thông thường, các thiết bị vào/ra kết hợp với một
dòng được biểu diễn như một dãy các ký tự.
Những tập tin văn bản, dữ liệu vào bằng bàn phím, đầu ra
cuối,…
Việc xử lý trực tiếp với các byte thô của dữ liệu khi
muốn làm việc với văn bản trong Java theo định
dạng Unicode là rất khó khăn
Hai lớp trừu tượng chính để giải quyết điều này
Reader
Writer
Nguyễn Đức Hiển – Bài giảng Lập trình Java
13
Reader và Writer
Giống như các lớp InputStream và OutputStream,
các lớp Reader và Writer cũng có nhiều lớp dẫn xuất
Đáng chú ý InputStreamReader
Dùng làm lớp bao bọc cho các đối tượng InputStream.
Chuyển đổi các byte thô khi chúng được đọc từ
InputStream thành các ký tự Unicode.
Ví dụ:
FileInputStream fs = new FileInputStream(“Employee.dat”)
InputStreamReader inp = new InputStreamReader (fs));
Thường dùng BufferedReader
Dùng làm lớp bao bọc cho lớp InputStreamReader
Ví dụ: BufferedReader kb = new BufferedReader( new
InputStreamReader(System.in));
Nguyễn Đức Hiển – Bài giảng Lập trình Java
14
Các dòng chuẩn
Java cung cấp sẵn các dòng cho đầu vào, đầu ra, và
lỗi chuẩn
System.in (InputStream)
System.out (PrintStream)
System.err (PrintStream)
Hai đối tượng System.out và System.err có kiểu
PrintStream khá hữu ích cung cấp các cơ chế để in
các kiểu dữ liệu cơ sở cũng như chuỗi vào dòng
System.in có kiểu InputStream là đối tượng nhập
chuẩn, thông thường chúng ta phải bao bọc nó để dễ
dàng sử dụng hơn
Nguyễn Đức Hiển – Bài giảng Lập trình Java
15
Đọc dữ liệu từ bàn phím
Như đã thấy, chúng ta có thể bao bọc lớp
InputStreamReader ngoài InputStream để làm cho
chúng trở nên hữu ích trong việc đọc dữ liệu ký tự
Sử dụng lớp bộ đệm BufferedReader cung cấp một
phương thức readLine() cho chức năng bổ sung.
Nguyễn Đức Hiển – Bài giảng Lập trình Java
16
StreamTokenizer
Lớp StreamTokenizer cung cấp chức năng tương tự
như StringTokenizer ngoại trừ nó mạnh hơn và lấy
dữ liệu của nó từ một Reader thay vì một String
Theo mặc định nó đoán nhận các số, chuỗi, từ, chú
thích, và khoảng trắng như các dấu hiệu (token)
Các dấu hiệu có thể được đọc một tại một thời điểm
và kiểu của chúng có thể được xác định để xử lý
chúng
Nguyễn Đức Hiển – Bài giảng Lập trình Java
17
Lớp File
Biểu diễn tên đường dẫn của một file (pathname) mà
file có thể có hay không tồn tại.
Không thật sự đại diện cho chính file!
Cung cấp sự hỗ trợ cho các thao tác như kiểm tra
nếu một file/thư mục tồn tại, nó là file hay thư mục,
kiểm tra quyền truy cập đọc/ghi, tạo và xóa file,…
Dùng cho sự tạo các đối tượng dòng file
Nguyễn Đức Hiển – Bài giảng Lập trình Java
18
Lớp File
Các đối tượng File có thể được tạo cho cả các file
lẫn thư mục
Cũng hỗ trợ cho các dấu tách đường dẫn.
Trên Unix tách đường dẫn là /, trong khi trên Windows là \
(được biểu diễn \\).
Tuy nhiên, cả hai dấu tách đều hợp lệ trên Windows.
Nguyễn Đức Hiển – Bài giảng Lập trình Java
19
Một số phương thức lớp File
exists() - kiểm tra file tồn tại
isDirectory() - kiểm tra file là một thư mục
isFile() - kiểm tra file thực sự là một file
isHidden() - kiểm tra file là ẩn
canRead() - kiểm tra file có thể được đọc bởi người
sử dụng hiện thời
canWrite() - kiểm tra file có thể được ghi bởi người
sử dụng hiện thời
getAbsolutePath() - trả lại đường dẫn tuyệt đối
getAbsoluteFile() - trả lại một đối tượng File
…
Nguyễn Đức Hiển – Bài giảng Lập trình Java
20
Các dòng File
Các đối tượng File có thể được dùng tạo ra các đối
tượng dòng như FileInputStream, FileOutputStream,
FileReader, hay FileWriter.
Đơn giản cung cấp đối tượng File vào trong một
trong số những phương thức khởi tạo thích hợp
Ví dụ:
Nguyễn Đức Hiển – Bài giảng Lập trình Java
21
Các dòng dữ liệu
Như đã thấy, cách xử lý các dòng có thể dòng các
byte hoặc dòng các ký tự
Đôi khi chúng ta muốn một mức độ trừu tượng cao
hơn và mong muốn đọc và ghi dữ liệu tới các dòng
theo dạng của các biến dữ liệu đơn hay toàn bộ đối
tượng lớp.
Lưu thông tin trạng thái chương trình vào một file
Gửi các biến dữ liệu cho các luồng (thread), các tiến trình
khác nhau hay gửi qua mạng
Nhiều ví dụ khác
Java có sẵn các lớp dòng tự động kiểm soát việc
chuyển đổi thông tin này thành các byte thô cần thiết
Nguyễn Đức Hiển – Bài giảng Lập trình Java
22
Các dòng dữ liệu
Java cung cấp hai lớp DataInputStream và
DataOutputStream tương ứng cho phép bạn đọc và
ghi các kiểu dữ liệu đơn nguyên tới các dòng vào/ra.
Lớp DataInputStream
readByte()
readChar()
readDouble()
readFloat()
readInt()
…
Lớp DataOutputStream có các phương thức write
tương ứng
Nguyễn Đức Hiển – Bài giảng Lập trình Java
23
Ví dụ
Nguyễn Đức Hiển – Bài giảng Lập trình Java
24
Dòng dữ liệu lớp
Thông thường, chương trình của chúng ta không chỉ
gồm có các kiểu dữ liệu đơn, chúng ta cũng có thể
muốn để đọc và ghi các lớp vào các dòng
Java cung cấp hai lớp để thực hiện điều này là
ObjectInputStream và ObjectOutputStream.
Các lớp ObjectInputStream và ObjectOutputStream
cung cấp chức năng tương tự như DataInputStream
và DataOutputStream, ngoại trừ chúng cũng có hỗ
trợ để đọc và ghi dữ liệu đối tượng thông qua các
phương thức readObject() và writeObject().
Nguyễn Đức Hiển – Bài giảng Lập trình Java
25
Sự tuần tự hóa (Serialization)
Các đối tượng chỉ có thể được ghi vào một dòng nếu
chúng là một kiểu lớp mà hiện thực giao tiếp
Serializable.
Đa số các lớp có sẵn trong Java hiện thực giao tiếp
Serializable
Serializable không định nghĩa bất kỳ phương thức
nào. Vì thế, để tạo một lớp do người sử dụng định
nghĩa có khả năng được ghi vào một dòng, thông
thường bạn chỉ cần thêm “implements Serializable”
trong khai báo lớp.