oop 13
DESCRIPTION
slide java o lopTRANSCRIPT
![Page 1: Oop 13](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/1.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/2.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/3.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/4.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/5.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/6.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/7.jpg)
Đị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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/8.jpg)
Đọ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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/9.jpg)
Đọ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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/10.jpg)
Đị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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/11.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/12.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/13.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/14.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/15.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/16.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/17.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/18.jpg)
Đọ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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/19.jpg)
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](https://reader033.vdocuments.pub/reader033/viewer/2022052622/55910d5b1a28ab2e148b457d/html5/thumbnails/20.jpg)
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