Chương 4.1

Nhập xuất

Chương 4.1: Nhập xuất

o Định dạng nhập/xuất o Khái niệm luồng o Các luồng byte o Các luồng ký tự o File truy cập ngẫu nhiên o Luồng nhập/xuất đối tượng. o Nhập/xuất với Scanner. o Nhập/xuất với JOptionPane

Định dạng nhập xuất

o Sử dụng hàm printf() và println() để định dạng kiểu

dữ liệu ở console.

Mã định dạng

Mô tả

%d

Kết quả định dạng như một số nguyên thập phân

%f

Kết quả định dạng như là một số thực

%o

Kết quả định dạng như là một số Octal (Cơ số 8)

%e

Kết quả định dạng như là một số thập phân trong kiểu số khoa học

%n

Kết quả được hiển thị trong một dòng mới

Định dạng nhập xuất

float i = 8; float j = 3;

o Ví dụ: Thực hiện đoạn chương trình sau: public static void main(String[] args){ System.out.println(“Ket qua cua i/j la: “ + i/j); System.out.printf(“Ket qua cua i/j la %.2f”, i/j); }

o Kết quả:

Luồng (Stream)

o Luồng là một “dòng chảy” của dữ liệu được gắn với

các thiết bị vào ra.

o Hai loại luồng:

 Luồng nhập: Gắn với các thiết bị nhập như bàn phím,

máy scan, file...

 Luồng xuất: Gắn với các thiết bị xuất như màn hình,

máy in, file,…

Các luồng cơ bản

o Byte streams

 Hỗ trợ việc xuất nhập dữ liệu trên byte, thường

được dùng khi đọc ghi dữ liệu nhị phân.

 InputStream: Luồng nhập byte cơ bản  OutputStream: Luồng xuất byte cơ bản

o Character streams

 Cho các ký tự Unicode  Reader: Luồng nhập ký tự cơ bản  Writer: Luồng xuất ký tự cơ bản

Các luồng cơ bản

o Các lớp luồng nằm trong gói java.io

Lớp trừu tượng trên cùng java.io.InputStream

Lớp trừu tượng trên cùng java.io.OutputStream

Dòng nhập byte vật lý Xử lý từng byte một

Dòng xuất byte vật lý Xử lý từng byte một

Biến / Đối tượng

Dòng nhập ký tự Xử lý theo đơn vị 2 byte

Dòng xuất ký tự Xử lý theo đơn vị 2 byte

Lớp trừu tượng trên cùng java.io.Reader

Lớp trừu tượng trên cùng java.io.Writer

Luồng byte

o input stream: sử dụng để đọc dữ liệu. o output stream: sử dụng để ghi dữ liệu.

Cây thừa kế InputStream

Các phương thức của InputStream

int available( )

Trả về số luợng bytes có thể đọc được từ luồng nhập

void close( )

Đóng luồng nhập và giải phóng tài nguyên hệ thống gắn với luồng. Không thành công sẽ ném ra một lỗi IOException

void mark(int numBytes)

Đánh dấu ở vị trí hiện tại trong luồng nhập

boolean markSupported( )

Kiểm tra xem luồng nhập có hỗ trợ phương thức mark() và

reset() không.

int read( )

Đọc byte tiếp theo từ luồng nhập

Đọc buffer.length bytes và lưu vào trong vùng nhớ buffer. Kết

int read(byte buffer[ ])

quả trả về số bytes thật sự đọc được

int read(byte buffer[ ], int offset, int numBytes)

Đọc numBytes bytes bắt đầu từ địa chỉ offset và lưu vào trong vùng nhớ buffer. Kết quả trả về số bytes thật sự đọc được

void reset( )

Nhảy con trỏ đến vị trí được xác định bởi việc gọi hàm mark() lần

sau cùng.

long skip(long numBytes)

Nhảy qua numBytes dữ liệu từ luồng nhập

Cây thừa kế OutputStream

Các phương thức của OutputStream

Đóng luồng xuất và giải phóng tài nguyên hệ thống gắn với

void close( )

luồng. Không thành công sẽ ném ra một lỗi IOException

void flush( )

Ép dữ liệu từ bộ đệm phải ghi ngay xuống luồng (nếu có)

void write(int b)

Ghi byte dữ liệu chỉ định xuống luồng

void write(byte buffer[ ])

Ghi buffer.length bytes dữ liệu từ mảng chỉ định xuống luồng

Ghi numBytes bytes dữ liệu từ vị trí offset của mảng chỉ định

void write(byte buffer[ ], int offset, int numBytes)

buffer xuống luồng

Đọc dữ liệu từ file

o Mở một file để đọc dữ liệu

FileNotFoundException

FileInputStream(String fileName) throws Nếu file không tồn tại: thì ném ra FileNotFoundException

o Đọc dữ liệu: dùng phương thức read()

int read( ) throws IOException: đọc từng byte từ file và trả về giá trị của byte đọc được. Trả về -1 khi hết file, và ném ra IOException khi có lỗi đọc.

o Đóng file: dùng phương thức close() void close( ) throws IOException: sau khi làm việc xong cần đóng file để giải phóng tài nguyên hệ thống đã cấp phát cho file.

13

FileNotFoundException

Ghi dữ liệu từ file o Mở một file để ghi dữ liệu

FileOutputStream(String fileName) throws Nếu file không tạo được: thì ném ra

FileNotFoundException

o Ghi dữ liệu xuống: dùng phương thức write()

void write(int byteval) throws IOException: ghi một byte

xác định bởi tham số byteval xuống file, và ném ra IOException khi có lỗi ghi.

o Đóng file: dùng phương thức close()

void close( ) throws IOException: sau khi làm việc xong

cần đóng file để giải phóng tài nguyên hệ thống đã cấp phát cho file.

Sử dụng FileInputStream & FileOutputStream

in = new FileInputStream(“d:/doc.txt"); out = new FileOutputStream(“d:/ghi.txt"); int c; while ((c = in.read()) != -1) { out.write(c); }

if (in != null) { in.close(); } if (out != null) { out.close(); } }

//Ví dụ chép dữ liệu từ file doc.txt sang ghi.txt import java.io.*; public class DocFile1 {

public static void main(String[] args) throws IOException { }

FileInputStream in = null; FileOutputStream out = null; try { }finally { }

Ví dụ

FileInputStream f = new FileInputStream("readme.txt"); int ch; while ( (ch = f.read()) != -1 ) { System.out.print((char)ch); } f.close();

System.out.println("File not found");

System.out.println("Can not read file");

import java.io.*; public class ReadFile { public static void main(String[] args){ try { } catch (FileNotFoundException d) { } catch (IOException d) { } }}

Ví dụ

System.out.println("Enter a string to write to file: "); int num = System.in.read(buffer); FileOutputStream f = new FileOutputStream("line.txt"); f.write(buffer, 0, num); f.close();

System.out.println("Error IO file");

import java.io.*; public class WriteFile { public static void main(String[] args) { byte buffer[] = new byte[80]; try { } catch (IOException e) { } }}

Luồng ký tự (Character Stream)

o Java platform lưu trữ những giá trị ký tự theo dạng

Unicode

o Tất cả các lớp character stream được kế thừa từ Reader

và Writer

o Có các lớp character stream:

 FileReader  FileWriter

Đọc ghi dữ liệu nhị phân

• Để đọc và ghi những giá trị nhị phân của các kiểu dữ

19

liệu trong java, chúng ta sử dụng: – DataInputStream – DataOutputStream.

Đọc ghi dữ liệu nhị phân

void writeBoolean(boolean val)

Ghi xuống luồng một giá trị boolean được xác định bởi val.

void writeByte (int val)

Ghi xuống luồng một byte được xác định bởi val.

void writeChar (int val)

Ghi xuống luồng một Char được xác định bởi val.

void writeDouble(double val)

Ghi xuống luồng một giá trị Double được xác định bởi val.

void writeFloat (float val)

Ghi xuống luồng một giá trị float được xác định bởi val.

void writeInt (int val)

Ghi xuống luồng một giá trị int được xác định bởi val.

void writeLong (long val)

Ghi xuống luồng một giá trị long được xác định bởi val.

void writeShort (int val)

Ghi xuống luồng một giá trị short được xác định bởi val.

Contructor: DataOutputStream(OutputStream outputStream) OutputStream: là luồng xuất dữ liệu. Để ghi dữ liệu ra file thì đối tượng outputStream có thể là FileOutputStream.

20

Đọc ghi dữ liệu nhị phân

boolean readBoolean( ) Đọc một giá trị boolean

Byte readByte( )

Đọc một byte

char readChar( )

Đọc một Char

double readDouble( )

Đọc một giá trị Double

float readFloat( )

Đọc một giá trị float

int readInt( )

Đọc một giá trị int

long readLong( )

Đọc một giá trị long

short readShort( )

Đọc một giá trị short

Contructor: DataInputStream(InputStream inputStream) InputStream: là luồng nhập dữ liệu. Để đọ dữ liệu từ file thì đối tượng InputStream có thể là FileInputStream.

21

Đọc ghi dữ liệu nhị phân

import java.io.*; class RWData{

public static void main(String args[]) throws IOException{ DataOutputStream dataOut;

DataInputStream dataIn; int i = 10; double d = 1023.56; boolean b = true; try {

dataOut = new DataOutputStream(new FileOutputStream("D:\\testdata"));

System.out.println("Cannot open file."); return;

}catch(IOException exc) { } try {

System.out.println("Writing " + i); dataOut.writeInt(i); System.out.println("Writing " + d); dataOut.writeDouble(d); System.out.println("Writing " + b);

22

Đọc ghi dữ liệu nhị phân

dataOut.writeBoolean(b); System.out.println("Writing " + 12.2 * 7.4); dataOut.writeDouble(12.2 * 7.4);

System.out.println("Write error.");

} catch(IOException exc) { }

new FileInputStream("D:\\testdata"));

System.out.println("Cannot open file."); return;

// Now, read them back. try { dataIn = new DataInputStream( } catch(IOException exc) { }

23

dataOut.close(); System.out.println();

Đọc ghi dữ liệu nhị phân

try { i = dataIn.readInt(); System.out.println("Reading " + i); d = dataIn.readDouble(); System.out.println("Reading " + d); b = dataIn.readBoolean(); System.out.println("Reading " + b); d = dataIn.readDouble(); System.out.println("Reading " + d);

}

System.out.println("Read error.");

}

catch(IOException exc) { dataIn.close(); } }

24

Cây kế thừa của Reader và Writer

Các phương thức của Reader

Các phương thức của Writer

Sử dụng FileReader & FileWriter

in = new FileReader("d:/doc.txt"); out = new FileWriter("d:/ghi.txt"); int c; while ((c = in.read()) != -1){ out.write(c); }

if (in != null) { in.close(); } if (out != null) { out.close(); }

public static void main(String[] args) throws IOException { FileReader in = null; FileWriter out = null; try { }finally { }

//Ví dụ chép dữ liệu từ file doc.txt sang ghi.txt import java.io.*; public class DocFile2 { }}

Sử dụng BufferedReader và BufferedWriter

o Một I/O không có bộ đệm có nghĩa là mỗi yêu cầu đọc

hoặc ghi được xử lý trực tiếp bởi HĐH.  Điều này làm chương trình kém hiệu quả, vì mỗi yêu cầu thường phải truy xuất đĩa, hoạt động mạng-> tốn thời gian.

o Java platform thực thi luồng I/O có bộ đệm

 Buffered input stream:

 Đọc dữ liệu từ vùng nhớ như là bộ đệm  API input được gọi chỉ khi bộ đệm rỗng.

 Buffered output stream:

 Ghi dữ liệu xuống bộ đệm.  API output chỉ được gọi khi buffer đầy.

Sử dụng BufferedReader và BufferedWriter

in = new BufferedReader(new FileReader("d:/doc.txt")); out = new BufferedWriter(new FileWriter("d:/ghi.txt")); int c; while ((c = in.read()) != -1) { out.write(c);}

if (in != null) { in.close(); } if (out != null) { out.close(); }

//Ví dụ chép dữ liệu từ file doc.txt sang ghi.txt import java.io.*; public class DocFile3 { public static void main(String[] args) throws IOException { BufferedReader in = null; BufferedWriter out = null;

try { } finally { }}}

Chuẩn Buffered Streams

o Tất cả các chương trình viết bằng java luôn tự động

import gói java.lang. Gói này có định nghĩa lớp System, nó có ba biến luồng được định nghĩa trước là in, out và err, chúng là các fields được khai báo static trong lớp System.  System.out: luồng xuất chuẩn, mặc định là console.

System.out là một đối tượng kiểu PrintStream.

 System.in: luồng nhập chuẩn, mặc định là bàn phím.

System.in là một đối tượng kiểu InputStream.  System.err: luồng lỗi chuẩn, mặc định cũng là console. System.err cũng là một đối tượng kiểu PrintStream giống System.out.

Ví dụ

byte data[] = new byte[100]; System.out.print("Enter some characters."); System.in.read(data); System.out.print("You entered: "); for(int i=0; i < data.length; i++)

System.out.print((char) data[i]);

{ }

//nhập liệu sử dụng phương thức System.in.read() import java.io.*; class ReadBytes { public static void main(String args[]) throws IOException }

32

Ví dụ

int b; b = 'X'; System.out.write(b); System.out.write('\n');

33

//nhập liệu sử dụng phương thức System.out.write() import java.io.*; class WriteDemo { public static void main(String args[]) { } }

Ví dụ

int iNumber = Integer.parseInt(siNumber); //chuyển sang định dạng số

float fNumber = Float.parseFloat(sfNumber); System.out.println("So nguyen:" + iNumber); System.out.println("So thuc:" + fNumber);

import java.io.*; public class TestInput{ public static void main(String[] args) throws Exception{ BufferedReader inStream = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Nhap mot so nguyen:"); String siNumber = inStream.readLine(); //đọc dữ liệu -> chuỗi System.out.print("Nhap mot so thuc:"); String sfNumber = inStream.readLine(); } }

Ví dụ

String str = "The example of OutputStream\n"; byte b[] = str.getBytes(); os.write(b);

System.out.println("Error: " + ie);

OutputStream os = System.out; //Monitor try{ } catch(IOException ie){ }

import java.io.*; public class OutStream1 { public static void main(String[] args) { } }

File truy nhập ngẫu nhiên

o Hai hạn chế của việc xử lý file thông qua luồng  Không thể đọc và ghi file cùng một lúc  Truy nhập file mang tính tuần tự

o Java hỗ trợ việc truy nhập và xử lý file một cách tự

do thông qua lớp RandomAccessFile.

File truy nhập ngẫu nhiên

o Các phương thức cơ bản

– RandomAccessFile(String name, String mode) // trong đó mode có thể là “r”, “w”, “rw”

– int readInt(); // đọc số nguyên – void writeInt(int v); // ghi số nguyên – long readLong(); // đọc số long – void writeLong(long v); // ghi số long – void seek(long pos); // di chuyển vị trí con trỏ file – long getFilePointer(); // lấy vị trí của con trỏ file – long length(); // lấy kích cỡ của file – void close(); // đóng file – ...

Sử dụng RandomAccessFile

System.out.println(“Error IO file”);

try{ RandomAccessFile f = new RandomAccessFile("randfile.dat","rw"); f.writeBoolean(true); f.writeInt(123456); f.writeChar('j'); f.writeDouble(1234.56); f.seek(1); System.out.println(f.readInt()); System.out.println(f.readChar()); System.out.println(f.readDouble()); f.seek(0); System.out.println(f.readBoolean()); f.close(); } catch (IOException e) { }

Luồng nhập/xuất đối tượng

Để lưu lại một đối tượng, ta có thể lưu lần lượt từng thuộc tính của nó. Khi đọc lại đối tượng ta phải tạo đối tượng mới từ các thuộc tính đã ghi. => Dài dòng, kém linh hoạt.

Java hỗ trợ đọc/ghi các đối tượng một cách đơn giản thông qua lớp ObjectInputStream và ObjectOutputStream.

Một đối tượng muốn có thể được đọc/ghi phải cài đặt giao tiếp java.io.Serializable

Ví dụ

//ghi lại tên và ngày sinh try{ FileOutputStream f = new FileOutputStream("birthfile.dat"); ObjectOutputStream oStream = new ObjectOutputStream(f); String babyName = "Briney Spears"; Date today = new Date(); oStream.writeObject(babyName); oStream.writeObject(today); oStream.close(); } catch (IOException e) { System.out.println(“Error IO file”); }

Ví dụ

//đọc tên và ngày sinh try{ FileInputStream f = new FileInputStream("birthfile.dat"); ObjectInputStream inStream = new ObjectInputStream(f); String name = (String) inStream.readObject(); Date birthDate = (Date) inStream.readObject(); System.out.println("Name of baby: " + name); System.out.println("Birth date: " + birthDate); inStream.close(); } catch (IOException e) { System.out.println(“Error IO file”); } catch (ClassNotFoundException e) { System.out.println(“Class of serialized object not found”); }

Đọc ghi đối tượng tự tạo

// file Student.java public class Student implements Serializable { private String name; private int age; Student(String name, int age) { this.name = name; this.age = age; } public String toString() { String ret = "My name is " + name + "\nI am " + age + " years old"; return ret; } }

Đọc ghi đối tượng tự tạo

ObjectOutputStream oStream = new

System.out.println(“Error IO file”);

// file WriteMyObject.java import java.io.*; public class WriteMyObject{ public static void main(String[] args){ try{ FileOutputStream f = new FileOutputStream("student.dat"); ObjectOutputStream(f); Student x = new Student("Bill Gates", 18); oStream.writeObject(x); oStream.close(); } catch (IOException e) { }

Đọc ghi đối tượng tự tạo

FileInputStream g = new FileInputStream("student.dat"); ObjectInputStream inStream = new ObjectInputStream(g); Student y = (Student) inStream.readObject(); System.out.println(y.toString()); inStream.close();

System.out.println(“Class not found”);

System.out.println(“Error IO file”);

try { }catch (ClassNotFoundException e) { } catch (IOException e) { } } }

Đọc ghi đối tượng tự tạo

throws IOException

– private

void

readObject(ObjectInputStream

in)

throws IOException, ClassNotFoundException

• Đối tượng có thể cài đặt 2 phương thức sau để thực hiện đọc/ghi theo cách riêng của mình. – private void writeObject(ObjectOutputStream out)

Đọc ghi đối tượng tự tạo

private void writeObject(ObjectOutputStream out) throws IOException

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException

Đối tượng có thể cài đặt 2 phương thức sau để thực hiện đọc/ghi theo cách riêng của mình.

Tóm tắt về xử lý file

Nên dùng DataInputStream và DataOutputStream để nhập/xuất các dữ liệu kiểu sơ cấp (int, float...)

Nên dùng ObjectInputStream và ObjectOutputStream nhập/xuất các đối tượng.

Nên kết hợp luồng file và luồng đọc/ghi ký tự để nhập xuất các file ký tự Unicode.

Nên dùng RandomAccessFile nếu muốn đọc/ghi tự do trên file.

Dùng lớp File để lấy thông tin về file

Nhập dữ liệu sử dụng lớp Scanner

o Scanner có nhiều tiến bộ hơn BufferReader. o Phân loại được dữ liệu mà người dùng nhập vào, có thể đọc

kiểu int, float, double,…

BufferedReader in1 = new BufferedReader(new InputStreamReader(System.in)); System.out.println(“Nhập vào một số nguyên: "); String siNumber = in1.readLine(); //đọc dữ liệu -> chuỗi int iNumber = Integer.parseInt(siNumber); //chuyển sang định dạng số.

Scanner in1=new Scanner(System.in); System.out.println(“Nhập vào một số nguyên: "); age= in1.nextInt(); //nhận trực tiếp kiểu int

Một số phương thức của lớp Scanner

o nextInt() : trả về kiểu int o nextFloat() : trả về kiểu float o nextBoolean() : trả về kiểu boolean o nextByte() : trả về kiểu byte o nextLine() : trả về kiểu String.

Nhập dữ liệu sử dụng lớp Scanner

public static void main(String[] args) { //Tạo một đối tượng Scanner Scanner in1=new Scanner(System.in); String name = ""; int age; System.out.println("Hãy nhập tên: "); name = in1.nextLine(); System.out.println("Hãy nhập tuổi: "); age= in1.nextInt(); System.out.println("Name is " + name +"!"); System.out.println("Age is " + age +"!"); }

import java.util.Scanner; public class GetInputFromKeyboard { }

Nhập xuất với JOptionPane

o JOptionPane là một lớp kế thừa từ lớp JComponent. o Khi biên dịch program thì nó sẽ hiện lên một dialog box

cho phép nhập dữ liệu.

o Một số phương thức:

 showConfirmDialog(): Hiển thị một câu hỏi lựa chọn

giống như yes no cancel

 showInputDialog(): Hiển thị box nhập  showMessageDialog(): Báo cho người dùng một sự

kiện vừa xảy ra.

Nhập xuất với JOptionPane

String name = ""; name=JOptionPane.showInputDialog(“Nhập vào tên

String msg = "Hello " + name + "!"; JOptionPane.showMessageDialog(null, msg); System.out.println("Name is:"+msg);

}

import javax.swing.JOptionPane; public class InputFromKeyboardJOptionPane { public static void main(String[] args) { của bạn:"); }

Các thao tác với tập tin và thư mục

o File (java.io.File): giúp thao tác với tập tin và thư mục o Một số hàm của lớp này như:

 isFile kiểm tra đúng là tập tin hay không.  isDirectory kiểm tra phải thư mục  exists kiểm tra tập tin hoặc thư mục có tồn tại.  canRead kiểm tra quyền đọc của tập tin hoặc thư mục  canWrite kiểm tra có quyền ghi không  setReadable cài đặt quyền đọc cho tập tin hoặc thư mục  setWritable cài đặt quyền ghi cho tập tin hoặc thư mục  mkdir tạo một thư mục tại đường dẫn đó  renameTo đổi tên tập tin hay thư mục  delete xóa tập tin hoặc thư mục  createNewFile tạo tập tin

Các thao tác với tập tin và thư mục

o Đọc thư mục d:/eclipse rồi in ra kết quả đường dẫn của

public static void main(String[] args) { File file = new File("d:/angiang/longxuyen"); if (!file.exists()) { if (file.mkdir()) {

System.out.println("Directoryreated!");

System.out.println("Failedreate directory!");

import java.io.File; public class CreateDirectoryExample { } else { } } } }

các file

Các thao tác với tập tin và thư mục

if(myDocumentFolder.exists() &&

File[] files = myDocumentFolder.listFiles(); for(File f : files) { System.out.println(f); }

import java.io.File; public class CreateDirectory1 { public static void main(String[] args) { File myDocumentFolder = new File("d:/eclipse"); myDocumentFolder.isDirectory() && myDocumentFolder.canRead()) { } }}

Bài tập tại lớp

• Bài 1: Viết chương trình đếm xem trong một file văn bản cho trước có bao nhiêu câu. Biết rằng các câu kết thúc bởi dấu chấm.

• Bài 2: Viết chương trình tạo file ghi 100 số Fibonacci đầu tiên. Viết chương trình thứ hai để đọc và hiển thị dữ liệu từ file này.