oop 13

20
Bài 13: Luồng dữ liệu Giảng viên: Nguyễn Thị Minh Huyền [email protected] Đỗ Thanh Hà [email protected]

Upload: thai-hoc-vu

Post on 29-Jun-2015

720 views

Category:

Spiritual


1 download

DESCRIPTION

slide java o lop

TRANSCRIPT

Page 1: Oop 13

Bài 13: Luồng dữ liệu

Giảng viên: Nguyễn Thị Minh Huyề[email protected]

Đỗ Thanh Hà[email protected]

Page 2: Oop 13

2009-2010 OOP - http://mim.hus.edu.vn/elearning 2

Tài liệu tham khảo

BigJava – chương 16

Page 3: Oop 13

2009-2010 OOP - http://mim.hus.edu.vn/elearning 3

Đọc tệp văn bản

Cách đơn giản nhất để đọc văn bản vào: dùnglớp Scanner

Để đọc văn bản từ tệp trên đĩa Tạo 1 đối tượng FileReader

Dùng đối tượng này để tạo 1 đối tượng ScannerFileReader reader = new FileReader("input.txt"); Scanner in = new Scanner(reader);

Dùng các phương thức của Scanner để đọc dữ liệu(next, nextLine, nextInt, nextDouble)

Page 4: Oop 13

Ghi tệp văn bản Để ghi lên 1 tệp, tạo 1 đối tượng PrintWriter

PrintWriter out = new PrintWriter("output.txt"); Nếu tệp đã tồn tại, nó sẽ bị xoá rỗng trước khi ghi dữ liệu

lên đó Nếu tệp chưa tồn tại, 1 tệp rỗng sẽ được tạo ra Dùng print và println để ghi vào 1 đối tượngPrintWriter out.println(29.95); out.println(new Rectangle(5, 10, 15, 25)); out.println("Hello, World!");

Phải đóng tệp sau khi ghi xong, nếu không dữ liệu đã ghisẽ bị mất out.close();

2009-2010 OOP - http://mim.hus.edu.vn/elearning 4

Page 5: Oop 13

Chương trình ví dụ Yêu cầu: Đọc tất cả các dòng từ 1 tệp văn bản, ghi vào 1

tệp mới sau khi thêm số dòng ở đầu mỗi dòng VD tệp đầu vào:

Mary had a little lamb Whose fleece was white as snow. And everywhere that Mary went, The lamb was sure to go!

Tệp kết quả: /* 1 */ Mary had a little lamb /* 2 */ Whose fleece was white as snow. /* 3 */ And everywhere that Mary went, /* 4 */ The lamb was sure to go!

Xem chương trình: ch16/text/LineNumberer.java

2009-2010 OOP - http://mim.hus.edu.vn/elearning 5

Page 6: Oop 13

Hộp thoại chọn tệp JFileChooser chooser = new JFileChooser();

FileReader in = null; if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {

File selectedFile = chooser.getSelectedFile(); reader = new FileReader(selectedFile); . . .

}

2009-2010

Page 7: Oop 13

Định dạng văn bản và nhị phân (1)

2 cách lưu dữ liệu trong tệp: dạng văn bản hoặcdạng nhị phân

Dạng văn bản: Lưu dãy kí tự, người đọc được Dùng lớp Reader/Writer và các lớp con của chúng

để đọc/ghi dữ liệu Dạng nhị phân:

Lưu dãy byte Dùng lớp InputStream/OutputStream và các lớp

con của chúng để đọc/ghi dữ liệu Tệp gọn hơn và việc đọc/ghi hiệu quả hơn

2009-2010 OOP - http://mim.hus.edu.vn/elearning 7

Page 8: Oop 13

Đọc 1 kí tự từ tệp văn bản

Dùng phương thức read của lớp Reader trả lại kí tự tiếp theo (nếu có) trong tệp dưới

dạng 1 số nguyên trả lại -1 nếu đã ở cuối tệp Ví dụ:

Reader reader = . . .; int next = reader.read(); char c; if (next != -1)

c = (char) next;

2009-2010 OOP - http://mim.hus.edu.vn/elearning 8

Page 9: Oop 13

Đọc 1 byte từ tệp nhị phân

Dùng phương thức read của lớpInputStream trả lại byte tiếp theo (nếu có) trong tệp dưới

dạng 1 số nguyên trả lại -1 nếu đã ở cuối tệp Ví dụ:

InputStream in = . . .; int next = in.read(); byte b; if (next != -1)

b = (byte) next;

2009-2010 OOP - http://mim.hus.edu.vn/elearning 9

Page 10: Oop 13

Định dạng văn bản và nhị phân (2)

Dùng phương thức write để ghi 1 kí tự hoặc 1 byte vào tệp

Các lớp vào/ra tệp chỉ cung cấp phương thứcread/write để đọc/ghi dữ liệu

Nguyên tắc của gói các lớp xử lí dòng dữ liệutrong Java: mỗi lớp có 1 nhiệm vụ rất tập trung VD: Lớp FileInputStream chỉ có nhiệm vụ tương

tác với tệp trên đĩa và đọc vào các byte Để đọc số, xâu kí tự, hay các đối tượng khác: kết nối lớp

này với các lớp khác

2009-2010 OOP - http://mim.hus.edu.vn/elearning 10

Page 11: Oop 13

VD chương trình mật mã hoá 1 tệp nhị phân Mật mã hoá: biến đổi dữ liệu gốc sao cho chỉ có người biết

phương pháp mật mã hoá và khoá mã mới đọc được dữ liệu Phương pháp mật mã hoá đơn giản: mật mã Caesar

Chọn khoá mã là 1 số trong khoảng từ 1 đến 25 VD: nếu khoá = 3, thay A bằng D, B bằng E, v.v. Để giải mã, trừ đi giá trị khoá mã

Xem chương trình: ch16/caesar (Encryptor.java, EncryptorTester.java, Crypt.java)

2009-2010 OOP - http://mim.hus.edu.vn/elearning 11

Page 12: Oop 13

Truy cập ngẫu nhiên và truy cập tuần tự

Truy cập tuần tự Tệp được xử lí theo từng byte lần lượt

Có thể kém hiệu quả

Truy cập ngẫu nhiên Cho phép truy cập vào 1 vị trí tuỳ ý trong tệp

Chỉ có tệp trên đĩa mới cho phép truy cập ngẫu nhiên, các dòng vào/ra System.in và System.out không thể truy cập ngẫu nhiên

Mỗi tệp trên đĩa có 1 vị trí con trỏ tệp, việc đọc/ghi tệp được thực hiện tại vị trí này.

2009-2010 OOP - http://mim.hus.edu.vn/elearning 12

Page 13: Oop 13

Lớp RandomAccessFile

Có thể mở tệp chỉ đọc ("r") hoặc cho phép đọc/ghi("rw")RandomAccessFile f =

new RandomAcessFile("bank.dat","rw");

Chuyển con trỏ tệp tới byte thứ n:f.seek(n);

Lấy vị trí hiện thời của con trỏ tệp:long n = f.getFilePointer(); // of type "long" because files can be very large

Tìm số byte trong tệp:long fileLength = f.length();

2009-2010 OOP - http://mim.hus.edu.vn/elearning 13

Page 14: Oop 13

Chương trình ví dụ (1)

Dùng 1 tệp truy cập ngẫu nhiên để lưu 1 tậpcác tài khoản ngân hàng Chương trình cho phép lấy 1 tài khoản và nạp tiền

vào đó Lớp RandomAccessFile

Lưu dữ liệu dạng nhị phân, 4 bytes cho số nguyên(int), 8 bytes cho số thực (double)

Cung cấp các hàm đọc/ghi 1 giá trị số Mỗi tài khoản ngân hàng sẽ được lưu bằng 12

bytes (4 bytes cho số TK, 8 bytes cho số tiền)

2009-2010 OOP - http://mim.hus.edu.vn/elearning 14

Page 15: Oop 13

Chương trình ví dụ (2)

Để đọc TK thứ n trong tệp: public BankAccount read(int n)

throws IOException { file.seek(n * RECORD_SIZE); int accountNumber = file.readInt(); double balance = file.readDouble(); return new BankAccount(accountNumber, balance);

}

2009-2010 OOP - http://mim.hus.edu.vn/elearning 15

Page 16: Oop 13

Chương trình ví dụ (3)

Để ghi TK thứ n vào tệp: public void write(int n, BankAccount account)

throws IOException { file.seek(n * RECORD_SIZE); file.writeInt(account.getAccountNumber());file.writeDouble(account.getBalance());

}

Xem chương trình ch16/random(BankData.java, BankDataTester.java)

2009-2010 OOP - http://mim.hus.edu.vn/elearning 16

Page 17: Oop 13

Các dòng dữ liệu đối tượng Lớp ObjectOutputStream / ObjectInputStream có thể lưu / đọc nguyên cả1 đối tượng (các trường dữ liệu của đối tượng) trênđĩa

Các đối tượng được lưu dưới dạng nhị phân, nên ta dùng dòng dữ liệu (stream)

VD: Ghi 1 đối tượng TK vào 1 tệp BankAccount b = . . .; ObjectOutputStream out = new ObjectOutputStream(

new FileOutputStream("bank.dat")); out.writeObject(b);

2009-2010 OOP - http://mim.hus.edu.vn/elearning 17

Page 18: Oop 13

Đọc 1 đối tượng TK từ tệp

readObject trả về 1 tham chiếu đối tượng kiểuObject Cần nhớ kiểu dữ liệu được ghi trong tệp và thực hiện

ép kiểu ObjectInputStream in = new ObjectInputStream(

new FileInputStream("bank.dat")); BankAccount b = (BankAccount) in.readObject();

readObject ném ngoại lệ có kiểm soátClassNotFoundException: cần bắt hoặc khaibáo ném ngoại lệ này

2009-2010 OOP - http://mim.hus.edu.vn/elearning 18

Page 19: Oop 13

Ghi/đọc ArrayList trên tệp

Có thể đọc/ghi nguyên cả mảng(ArrayList) trên 1 tệp

Ghi ArrayList<BankAccount> a = new ArrayList<BankAccount>(); // Now add many BankAccount objects into a out.writeObject(a);

Đọc ArrayList<BankAccount> a = (ArrayList<BankAccount>)

in.readObject();

2009-2010 OOP - http://mim.hus.edu.vn/elearning 19

Page 20: Oop 13

Serializable Các đối tượng được ghi vào 1 dòng dữ liệu đối tượng phải thuộc

vào 1 lớp cài đặt giao diện Serializable class BankAccount implements Serializable {

. . . }

Giao diện Serializable không có phương thức nào Tuần tự hoá (Serialization): quá trình lưu đối tượng vào 1 dòng

dữ liệu (stream) Mỗi đối tượng được cấp 1 số xê-ri trên dòng dữ liệu Nếu cùng 1 đối tượng được ghi 2 lần, thì lần thứ 2 chỉ có số xê-ri

được ghi lên đĩa Khi đọc dữ liệu, các số xê-ri đúp được khôi phục lại như các tham

chiếu tới cùng 1 đối tượng Xem VD: ch16/serial

2009-2010 OOP - http://mim.hus.edu.vn/elearning 20