Table of Contents
- 1. Đọc ký tự từ console
- 2. Sử dụng FileInputStream và FileOutputStream
- 3. Sử dụng ByteArrayInputStream & ByteArrayOutputStream
- 4. Sử dụng ObjectInputStream và ObjectOutputStream
- 5. Sử dụng DataInputStream và DataOutputStream
- 6. Sử dụng FilterInputStream và FilterOutputStream
- 7. Sử dụng SequenceInputStream
- 8. Sử dụng PipedInputStream và PipedOutputStream
Ở bài viết trước tôi đẫ giới thiệu với các bạn Luồng vào ra (I/O) trong Java. Ở bài này chúng ta sẽ cùng tìm hiểu các lớp hỗ trợ xử lý luồng nhị phân trong Java.

1. Đọc ký tự từ console
1.1. Ví dụ nhập từng ký tự từ bàn phím và hiên thị kết quả lên màn hình
package com.maixuanviet.console; import java.io.IOException; import java.io.InputStream; public class ReadByteConsole { public static void main(String[] args) throws IOException { InputStream is = System.in; while (true) { System.out.print("Nhập 1 ký tự: "); int ch = is.read(); if (ch == 'q') { System.out.println("Finished!"); break; } is.skip(2); // Loại bỏ 2 ký tự \r và \n System.out.println("Ký tự nhận được: " + (char) ch); } } }
Kết quả thực thi chương trình trên:
Nhập 1 ký tự: g Ký tự nhận được: g Nhập 1 ký tự: p Ký tự nhận được: p Nhập 1 ký tự: q Finished!
1.2. Ví dụ nhập một chuỗi ký tự từ bàn phím và hiên thị kết quả lên màn hình
package com.maixuanviet.console; import java.io.IOException; public class ReadByteConsole2 { public static void main(String[] args) throws IOException { while (true) { System.out.print("Nhập chuỗi ký tự: "); byte[] bytes = new byte[100]; // Tạo vùng đệm để nhập chuỗi int length = System.in.read(bytes); String str = new String(bytes, 0, length - 2); if (str.equalsIgnoreCase("EXIT")) { System.out.println("Finished!"); break; } System.out.println("Chuỗi nhận được: " + str); } } }
Kết quả thực thi chương trình trên:
Nhập chuỗi ký tự: maixuanviet.com Chuỗi nhận được: maixuanviet.com Nhập chuỗi ký tự: exit Finished!
2. Sử dụng FileInputStream và FileOutputStream
Lớp FileInputStream trong java đọc được các byte từ một input file. Nó được sử dụng để đọc dữ liệu theo định dạng byte (các byte stream) như dữ liệu hình ảnh, âm thanh, video vv. Bạn cũng có thể đọc các dữ liệu có định dạng ký tự. Tuy nhiên, để đọc các dòng ký tự (các character stream), bạn nên sử dụng lớp FileReader.
Java FileOutputStream là một output stream được sử dụng để ghi dữ liệu vào một file theo định dạng byte (byte stream). Sử dụng lớp FileOutputStream trong java, nếu bạn phải ghi các giá trị nguyên thủy vào một file. Bạn có thể ghi dữ liệu theo định dạng byte hoặc định dạng ký tự thông qua lớp FileOutputStream. Tuy nhiên, đối với các dữ liệu được ghi theo ký tự, sử dụng FileWriter thích hợp hơn FileOutStream.
2.1. Ví dụ đọc nội dung của file sử dụng FileInputStream
package com.maixuanviet.bytestream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class InputStreamExample { public static void main(String[] args) throws IOException { // Tạo một đối tượng InputStream: Luồng đọc một file. InputStream is = new FileInputStream("data/test.txt"); int i = -1; // Đọc lần lượt các byte (8bit) trong luồng và lưu vào biến i // Khi đọc ra giá trị -1 nghĩa là kết thúc luồng. while ((i = is.read()) != -1) { System.out.println((char) i); } is.close(); } }
Kết quả thực thi chương trình trên:
H e l l o I n p u t S t r e a m
2.2. Ví dụ đọc nhiều byte sử dụng FileInputStream
package com.maixuanviet.bytestream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class InputStreamExample2 { public static void main(String[] args) throws IOException { // Tạo một luồng đầu vào bằng cách đọc một file InputStream in = new FileInputStream("data/test.txt"); // Mảng để mỗi lần đọc các byte từ luồng thì tạm thời để lên đó // Ta dùng mảng 10 byte byte[] bytes = new byte[10]; int i = -1; // Đọc các byte trong luồng và gán lên các phần tử của mảng. // Giá trị i là số đọc được của 1 lần. (i sẽ <= 10). // Khi không còn phần tử trong luồng i sẽ = -1 while ((i = in.read(bytes)) != -1) { // Tạo String từ các byte đọc được String s = new String(bytes, 0, i); System.out.println(s); } in.close(); } } [/code] <!-- /wp:shortcode --> <!-- wp:paragraph --> <p>Kết quả thực thi chương trình trên:</p> <!-- /wp:paragraph --> <!-- wp:shortcode --> Hello Inpu tStream
2.3. Ví dụ ghi nội dung ra file sử dụng FileOutputStream
package com.maixuanviet.bytestream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class OutputStreamExample { public static void main(String[] args) throws IOException { // Tạo một luồng ký tự đầu ra với mục đích ghi thông tin vào file OutputStream os = new FileOutputStream("data/output.txt"); // Tạo một mảng byte ,ta sẽ ghi các byte này vào file nói trên . byte[] by = new byte[] { 'g', 'p', 'c', 'o', 'd', 'e', 'r', '.', 'c', 'o', 'm' }; // Ghi lần lượt các ký tự vào luồng for (int i = 0; i < by.length; i++) { byte b = by[i]; // Ghi ký tự vào luồng os.write(b); } // Đóng luồng đầu ra lại việc ghi xuống file hoàn tất. os.close(); } } [/code] <!-- /wp:shortcode --> <!-- wp:heading {"level":3} --> <h3>2.4. Ví dụ ghi nhiều byte sử dụng FileOutputStream</h3> <!-- /wp:heading --> <!-- wp:shortcode --> package com.maixuanviet.bytestream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class OutputStreamExample2 { public static void main(String[] args) throws IOException { // Tạo một luồng nhị phân đầu ra với mục đích ghi thông tin vào file OutputStream os = new FileOutputStream("data/output2.txt"); // Tạo một mảng byte ,ta sẽ ghi các byte này vào file nói trên . byte[] b1 = new byte[] { 'g', 'p', 'c', 'o', 'd', 'e', 'r' }; byte[] b2 = new byte[] { '.', 'c', 'o', 'm' }; byte[] b3 = new byte[] { 13, 10 }; // Xuống dòng mới byte[] b4 = new byte[] { 'I', '/', 'O' }; // Ghi cả các byte trong mảng byte[] by vào luồng os.write(b1); // Đẩy các byte hiện có trên luồng xuống file . os.flush(); // Tiếp tục ghi các byte trong mảng thứ 2 vào luồng os.write(b2); os.write(b3); os.write(b4); // Đóng luồng vào công việc ghi thành công . os.close(); } }
3. Sử dụng ByteArrayInputStream & ByteArrayOutputStream
ByteArrayInputStream bao gồm hai từ: ByteArray và InputStream. Tên của nó cho thấy, nó có thể được sử dụng để đọc mảng byte như là input stream.
- Lớp ByteArrayInputStream trong java chứa một bộ đệm bên trong được sử dụng để đọc mảng byte dưới dạng luồng.
- Bộ đệm của ByteArrayInputStream tự động tăng theo kích thước dữ liệu.
Lớp ByteArrayOutputStream trong java được sử dụng để ghi dữ liệu chung vào nhiều file. Trong luồng này, dữ liệu được ghi vào mảng byte có thể được ghi vào nhiều stream sau đó.
- ByteArrayOutputStream giữ một bản sao của dữ liệu và chuyển tiếp nó đến nhiều stream.
- Bộ đệm của ByteArrayOutputStream tự động tăng theo kích thước dữ liệu.
3.1. Ví dụ sử dụng ByteArrayInputStream
package com.maixuanviet.bytestream; import java.io.ByteArrayInputStream; import java.io.IOException; public class ByteArrayInputStreamExample { public static void main(String args[]) throws IOException { byte[] buf = new byte[] { 'g', 'p', 'c', 'o', 'd', 'e', 'r', '.', 'c', 'o', 'm' }; // Create the new byte array input stream ByteArrayInputStream byt = new ByteArrayInputStream(buf); int k = 0; while ((k = byt.read()) != -1) { // Conversion of a byte into character char ch = (char) k; System.out.println("ASCII value of Character is:" + k + " - Special character is: " + ch); } } }
Kết quả thực thi chương trình trên:
ASCII value of Character is:103 - Special character is: g ASCII value of Character is:112 - Special character is: p ASCII value of Character is:99 - Special character is: c ASCII value of Character is:111 - Special character is: o ASCII value of Character is:100 - Special character is: d ASCII value of Character is:101 - Special character is: e ASCII value of Character is:114 - Special character is: r ASCII value of Character is:46 - Special character is: . ASCII value of Character is:99 - Special character is: c ASCII value of Character is:111 - Special character is: o ASCII value of Character is:109 - Special character is: m
3.2. Ví dụ sử dụng ByteArrayOutputStream
package com.maixuanviet.bytestream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class ByteArrayOutputStreamExample { public static void main(String args[]) throws IOException { FileOutputStream fout1 = new FileOutputStream("data/f1.txt"); FileOutputStream fout2 = new FileOutputStream("data/f2.txt"); ByteArrayOutputStream bout = new ByteArrayOutputStream(); bout.write(65); bout.writeTo(fout1); bout.writeTo(fout2); bout.flush(); bout.close();// has no effect System.out.println("Success..."); } }
Thực thi chương trình trên: có 2 file f1 và f2 được tạo ra trong thư mục data của project.
Hình bên dưới minh họa hoạt động của ví dụ này:

4. Sử dụng ObjectInputStream và ObjectOutputStream
ObjectInputStream, ObjectOutputStream cho phép bạn đọc hoặc ghi một Object vào luồng. Các Object này phải là kiểu Serializable.
Student.java
package com.maixuanviet.bytestream; import java.io.Serializable; public class Student implements Serializable { private static final long serialVersionUID = -266706354210367639L; private int id; private String name; private int age; public Student(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + "]"; } }
4.1. Ví dụ sử dụng ObjectOutputStream để ghi đối tượng vào file
package com.maixuanviet.bytestream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class ObjectOutputStreamExample { public static void main(String args[]) throws Exception { ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(new FileOutputStream("data/student.txt")); Student student = new Student(1, "maixuanviet.com", 28); oos.writeObject(student); oos.flush(); } catch (IOException ex) { ex.printStackTrace(); } finally { oos.close(); } System.out.println("success..."); } }
4.2. Ví dụ sử dụng ObjectInputStreamExample để đọc đối tượng từ file
package com.maixuanviet.bytestream; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class ObjectInputStreamExample { public static void main(String args[]) throws Exception { ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream("data/student.txt")); Student student = (Student) ois.readObject(); System.out.println(student); } catch (IOException ex) { ex.printStackTrace(); } finally { ois.close(); } } }
Thực thi chương trình ObjectOutputStreamExample, một file student.txt được tạo ra trong thư mục data của project như sau:

Thực thi chương trình ObjectInputStreamExample, ta được nội dung như sau:
Student [id=1, name=maixuanviet.com, age=28]
5. Sử dụng DataInputStream và DataOutputStream
Lớp DataInputStream trong java cho phép một ứng dụng đọc dữ liệu nguyên thủy từ luồng đầu vào một cách độc lập với máy. Ứng dụng Java thường sử dụng DataOutputStream để ghi dữ liệu mà sau này có thể được đọc bởi một DataInputStream.
Lớp DataOutputStream trong java cho phép một ứng dụng ghi các kiểu dữ liệu Java nguyên thủy đến output stream một cách độc lập với máy. Ứng dụng Java thường sử dụng DataOutputStream để ghi dữ liệu mà sau này có thể được đọc bởi một DataInputStream.
5.1. Ví dụ ghi file sử dụng DataOutputStream
package com.maixuanviet.bytestream; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class DataOutputStreamExamaple { public static void main(String[] args) throws IOException { int id = 1; String name = "maixuanviet.com"; OutputStream file = new FileOutputStream("data/test3.txt"); DataOutputStream data = new DataOutputStream(file); data.writeInt(id); data.writeUTF(name); data.flush(); data.close(); System.out.println("Succcess..."); } }
Thực thi chương trình trên, một file test3.txt được tạo ra trong thư mục data của dự án.
5.2. Ví dụ đọc file sử dụng DataInputStream
package com.maixuanviet.bytestream; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class DataInputStreamExample { public static void main(String[] args) throws IOException { InputStream input = new FileInputStream("data/test3.txt"); DataInputStream inst = new DataInputStream(input); int id = inst.readInt(); String name = inst.readUTF(); System.out.println("Id: " + id + ", Name: " + name); inst.close(); } }
Kết quả thực thi chương trình trên:
Id: 1, Name: maixuanviet.com
6. Sử dụng FilterInputStream và FilterOutputStream
Lớp FilterOutputStream trong java extends lớp OutputStream. Nó cung cấp các lớp con khác nhau như BufferedOutputStream và DataOutputStream để cung cấp các chức năng bổ sung. Vì vậy, nó ít được sử dụng riêng lẻ.
Lớp FilterInputStream trong java extends lớp InputStream. Nó cung cấp các lớp con khác nhau như BufferedInputStream và DataInputStream để cung cấp chức năng bổ sung. Vì vậy, nó ít được sử dụng riêng lẻ.
6.1. Ví dụ ghi file sử dụng FilterOutputStream
package com.maixuanviet.bytestream; import java.io.File; import java.io.FileOutputStream; import java.io.FilterOutputStream; import java.io.IOException; public class FilterOutputStreamExample { public static void main(String[] args) throws IOException { FileOutputStream file = null; FilterOutputStream filter = null; try { file = new FileOutputStream(new File("data/test.txt")); filter = new FilterOutputStream(file); String s = "maixuanviet.com"; byte b[] = s.getBytes(); filter.write(b); filter.flush(); System.out.println("Success..."); } catch (IOException ex) { ex.printStackTrace(); } finally { filter.close(); file.close(); } } }
Thực thi chương trình trên, một file test.txt được tạo ra trong thư mục data của project.
6.2. Ví dụ đọc file sử dụng FilterInputStream
package com.maixuanviet.bytestream; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FilterInputStream; import java.io.IOException; public class FilterInputStreamExample { public static void main(String[] args) throws IOException { FileInputStream file = null; FilterInputStream filter = null; try { file = new FileInputStream(new File("data/test.txt")); filter = new BufferedInputStream(file); int k = 0; while ((k = filter.read()) != -1) { System.out.print((char) k); } } catch (IOException ex) { ex.printStackTrace(); } file.close(); filter.close(); } }
Kết quả thực thi chương trình trên:
maixuanviet.com
7. Sử dụng SequenceInputStream
Thông thường bạn đã quen thuộc với việc đọc một file nào đó và thu được một luồng đầu vào .Nhưng trong thực tế đôi khi bạn cần đọc từ nhiều file và lấy các dữ liệu đó ghép với nhau để ghi thành 1 file khác chẳng hạn .Vậy là ý tưởng ghép nhiều luồng đầu vào với nhau để thành một luồng lớn hơn nối đuôi nhau . Chúng ta đang nói đến class java.io.SequenceInputStream. Khái niệm này không có tương ứng cho luồng đầu ra.
package com.maixuanviet.bytestream; import java.io.FileInputStream; import java.io.IOException; import java.io.SequenceInputStream; public class SequenceInputStreamExample { public static void main(String args[]) throws Exception { FileInputStream input1 = null; FileInputStream input2 = null; SequenceInputStream inst = null; try { input1 = new FileInputStream("data/test1.txt"); input2 = new FileInputStream("data/test2.txt"); inst = new SequenceInputStream(input1, input2); int j; while ((j = inst.read()) != -1) { System.out.print((char) j); } } catch (IOException ex) { ex.printStackTrace(); } finally { inst.close(); input1.close(); input2.close(); } } }
8. Sử dụng PipedInputStream và PipedOutputStream

Đặt ra một tình huống bạn có 2 luồng một luồng đầu vào và một luồng đầu ra. Chẳng hạn luồng đầu vào dữ liệu A đọc một file , lấy thông tin từ luồng này ghi vào luồng dữ liệu B đầu ra là một file khác. Hai luồng A và B trong tình huống này là tách riêng nhau. Vì vậy trong ứng dụng bạn phải có 3 thao tác:
- Tạo luồng dữ liệu đọc A
- Tạo luồng ghi dữ liệu B
- Đọc từ A ghi vào B …
Hai thao tác đầu phải có, nhưng bạn muốn bỏ đi thao tác thứ 3. Nghĩa là có một cái gì đó liên hệ ngầm với nhau giữa 2 luồng (vào-ra) ,để sao cho những byte xuất hiện trên luồng đầu đọc A lập tức được ghi tự động vào B. Đó được gọi là liên hệ đường ngầm giữa 2 luồng vào và ra.
package com.maixuanviet.bytestream; import java.io.IOException; import java.io.InputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; public class PipeStreamExample { private InputStream pipedInputStream; public static void main(String[] args) throws IOException, InterruptedException { new PipeStreamExample().test(); } private void test() throws IOException, InterruptedException { // Tạo một 'pipedOutputStream', PipedOutputStream pipedOutputStream = new PipedOutputStream(); // Dữ liệu ghi vào 'pipedOutputStream' // sẽ tự động xuất hiện tại 'pipedInputStream'. pipedInputStream = new PipedInputStream(pipedOutputStream); new ThreadRead().start(); char[] chs = new char[] { 'a', 'a', 'b', 'c', 'e' }; // Ghi dữ liệu vào 'pipedOutputStream'. for (char ch : chs) { pipedOutputStream.write(ch); Thread.sleep(1000); } pipedOutputStream.close(); } // Một Thread đọc dữ liệu xuất hiện trên 'pipedInputStream'. class ThreadRead extends Thread { @Override public void run() { try { int data = 0; while ((data = pipedInputStream.read()) != -1) { System.out.println((char) data); } } catch (Exception e) { e.printStackTrace(); } finally { closeQuietly(pipedInputStream); } } } private void closeQuietly(InputStream is) { if (is != null) { try { is.close(); } catch (IOException e) { } } } }
Kết quả thực thi chương trình trên:
a a b c e