Hướng dẫn và ví dụ Java InputStream
1. InputStream
InputStream là một lớp nằm trong package java.io, nó là một lớp cơ sở đại diện cho một dòng chảy của các bytes (stream of bytes) có được khi đọc một nguồn dữ liệu nào đó, chẳng hạn file.
public abstract class InputStream implements Closeable
- ByteArrayInputStream
- FileInputStream
- FilterInputStream
- BufferedInputStream
- DataInputStream
- PushbackInputStream
- ObjectInputStream
- PipedInputStream
- SequenceInputStream
- AudioInputStream
- CheckedInputStream
- DeflaterInputStream
- InflaterInputStream
- CipherInputStream
- DigestInputStream
Về cơ bản bạn không thể sử dụng lớp InputStream một cách trực tiếp vì nó là một lớp trừu tượng, tuy nhiên trong trường hợp cụ thể bạn có thể sử dụng một trong các lớp con của nó.
Hãy xem một ví dụ về một file văn bản được mã hoá UTF-8:
utf8-file-without-bom.txt
JP日本-八洲
UTF-8 sử dụng 1, 2, 3 hoặc 4 bytes để lưu trữ một ký tự. Hình ảnh dưới đây cho thấy các bytes trong file nói trên.
FileInputStream là một lớp con của InputStream thường được sử dụng để đọc các file và chúng ta sẽ nhận được một dòng chảy các bytes (stream of bytes).
InputStream Methods
public static InputStream nullInputStream()
public abstract int read() throws IOException
public int read(byte[] b) throws IOException
public int read(byte[] b, int off, int len) throws IOException
public byte[] readAllBytes() throws IOException
public byte[] readNBytes(int len) throws IOException
public int readNBytes(byte[] b, int off, int len) throws IOException
public long skip(long n) throws IOException
public int available() throws IOException
public void close() throws IOException
public synchronized void mark(int readlimit)
public synchronized void reset() throws IOException
public boolean markSupported()
public long transferTo(OutputStream out) throws IOException
2. read()
public int read() throws IOException
Phương thức read() được sử dụng để đọc một byte, giá trị của byte được trả về là một số nguyên (integer) trong khoảng 0 đến 255, hoặc trả về -1 nếu đã tiến tới cuối stream.
Phương thức này sẽ chặn (block) cho tới khi byte sẵn có để đọc hoặc xẩy ra lỗi IO, hoặc đã tiến tới cuối stream.
utf8-file-without-bom.txt
JP日本-八洲
Ví dụ:
InputStream_read_ex1.java
package org.o7planning.inputstream.ex;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class InputStream_read_ex1 {
// Windows path: C:/somepath/utf8-file-without-bom.txt"
private static final String filePath = "/Volumes/Data/test/utf8-file-without-bom.txt";
public static void main(String[] args) throws IOException {
// FileInputStream is a subclass of InputStream.
InputStream is = new FileInputStream(filePath);
int code;
while((code = is.read()) != -1) {
System.out.println(code + " " + (char)code);
}
is.close();
}
}
Output:
74 J
80 P
230 æ
151
165 ¥
230 æ
156
172 ¬
45 -
229 å
133
171 «
230 æ
180 ´
178 ²
3. read(byte[])
public int read(byte[] b) throws IOException
Phương thức read(byte[]) đọc các bytes từ InputStream và gán vào các phần tử của mảng và trả về số bytes vừa đọc được. Phương thức này trả về -1 nếu đã tiến tới cuối stream.
Phương thức này sẽ chặn (block) cho tới khi các bytes sẵn có để đọc hoặc xẩy ra lỗi IO, hoặc đã tiến tới cuối stream.
Về cơ bản sử dụng phương thức read(byte[]) sẽ có hiệu xuất cao hơn so với phương thức read(), vì nó giảm số lần cần đọc từ stream.
InputStream_read_ex2.java
package org.o7planning.inputstream.ex;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class InputStream_read_ex2 {
public static void main(String[] args) throws IOException {
String url = "https://s3.o7planning.com/txt/utf8-file-without-bom.txt";
InputStream is = new URL(url).openStream();
// Create a temporary byte array.
byte[] tempByteArray = new byte[10];
int byteCount = -1;
int nth = 0;
while ((byteCount = is.read(tempByteArray)) != -1) {
nth++;
System.out.println("--- Read th: " + nth + " ---");
System.out.println(" >> Number of bytes read: " + byteCount +"\n");
for(int i= 0; i < byteCount; i++) {
// bytes are in range [-128,127]
// Convert byte to unsigned byte. [0, 255].
int code = tempByteArray[i] & 0xff;
System.out.println(tempByteArray[i] + " " + code + " " + (char)code);
}
}
is.close();
}
}
Output:
--- Read th: 1 ---
>> Number of bytes read: 10
74 74 J
80 80 P
-26 230 æ
-105 151
-91 165 ¥
-26 230 æ
-100 156
-84 172 ¬
45 45 -
-27 229 å
--- Read th: 2 ---
>> Number of bytes read: 5
-123 133
-85 171 «
-26 230 æ
-76 180 ´
-78 178 ²
Chú ý: Kiểu dữ liệu byte bao gồm các số nguyên (integer) nằm trong phạm vi từ -128 đến 127. Bạn có thể chuyển đổi nó thành số nguyên không dấu (unsigned integer) có phạm vi từ 0 đến 255.
- Convert byte to unsigned byte
4. read(byte[], int, int)
public int read(byte[] b, int offset, int len) throws IOException
Phương thức read(byte[],int,int) đọc các bytes và gán vào các phần tử của mảng từ chỉ số offset tới chỉ số offset+len, và trả về số bytes vừa đọc được. Phương thức này trả về -1 nếu đã tiến tới cuối stream.
Phương thức này sẽ chặn (block) cho tới khi các bytes sẵn có để đọc, hoặc xẩy ra lỗi IO, hoặc đã tiến tới cuối stream.
5. readAllBytes()
public byte[] readAllBytes() throws IOException
Ví dụ:
InputStream_readAllBytes_ex1.java
package org.o7planning.inputstream.ex;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class InputStream_readAllBytes_ex1 {
public static void main(String[] args) throws IOException {
String url = "https://s3.o7planning.com/txt/utf8-file-without-bom.txt";
InputStream is = new URL(url).openStream();
byte[] allBytes = is.readAllBytes();
String content = new String(allBytes, "UTF-8");
System.out.println(content);
is.close();
}
}
Output:
JP日本-八洲
6. readNBytes(int len)
public byte[] readNBytes(int len) throws IOException
Phương thức readNBytes(int) đọc tối đa "len"bytes từ InputStream, và trả về một mảng byte đọc được. Nếu mảng trả về là rỗng nghĩa là đã tiến tới cuối stream.
Phương thức này sẽ chặn (block) cho tới khi "len"bytes được đọc, hoặc xẩy ra lỗi IO, hoặc đã tiến tới cuối stream.
Ví dụ:
InputStream_readNBytes_ex1.java
package org.o7planning.inputstream.ex;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class InputStream_readNBytes_ex1 {
// Windows path: C:/somepath/utf8-file-without-bom.txt"
private static final String filePath = "/Volumes/Data/test/utf8-file-without-bom.txt";
public static void main(String[] args) throws IOException {
// FileInputStream is a subclass of InputStream.
InputStream is = new FileInputStream(filePath);
byte[] bytes = null;
int nth = 0;
while( true) {
nth++;
bytes = is.readNBytes(10);
System.out.println("--- Read th: " + nth + " ---");
System.out.println(" >> Number of bytes read: " + bytes.length +"\n");
if(bytes.length == 0) {
break;
}
for(int i= 0; i< bytes.length; i++) {
// bytes are in range [-128,127]
// Convert byte to unsigned byte. [0, 255].
int code = bytes[i] & 0xff;
System.out.println(bytes[i] + " " + code + " " + (char)code);
}
}
is.close();
}
}
Output:
--- Read th: 1 ---
>> Number of bytes read: 10
74 74 J
80 80 P
-26 230 æ
-105 151
-91 165 ¥
-26 230 æ
-100 156
-84 172 ¬
45 45 -
-27 229 å
--- Read th: 2 ---
>> Number of bytes read: 5
-123 133
-85 171 «
-26 230 æ
-76 180 ´
-78 178 ²
--- Read th: 3 ---
>> Number of bytes read: 0
7. readNBytes(byte[] b, int off, int len)
public int readNBytes(byte[] b, int offset, int len) throws IOException
Phương thức readNBytes(byte[],int,int) đọc tối đa "len"bytes từ InputStream, và gán các bytes đọc được vào các phần tử của mảng từ chỉ số offset đến offset+len, và trả về số bytes đọc được. Trả về -1 nếu đã tiến tới cuối stream.
read(byte[],int,int) vs readNBytes(byte[],int,int)
public int read(byte[] b, int offset, int len) throws IOException
public int readNBytes(byte[] b, int offset, int len) throws IOException
Hai phương thức read(byte[],int,int) và readNBytes(byte[],int,int) khá giống nhau. Nhưng điều khác biệt có thể xẩy ra trong tình huống sau:
Phương thức read(byte[] b,int offset, int len) không đảm bảo rằng "len" bytes sẽ được đọc từ stream cho dù chưa tiến tới cuối stream.
Phương thức readNBytes(byte[] b,int offset, int len) đảm bảo rằng "len" bytes sẽ được đọc từ stream nếu chưa tiến tới cuối của stream.
8. close()
public void close() throws IOException
Đóng stream này và giải phóng mọi tài nguyên hệ thống được liên kết với nó. Khi stream đã bị đóng, các lệnh gọi tiếp read(), mark(), reset() hoặc skip() sẽ tạo ra một IOException. Đóng stream đã đóng trước đó không có tác dụng.
public interface Closeable extends AutoCloseable
Lớp InputStream thi hành interface Closeable. Nếu bạn viết code theo quy tắc của AutoCloseable thì hệ thống sẽ tự đóng stream cho bạn mà không cần phải gọi trực tiếp phương thức close().
InputStream_close_ex1.java
package org.o7planning.inputstream.ex;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class InputStream_close_ex1 {
// Or Windows path: C:/Somefolder/utf8-file-without-bom.txt
private static final String file_path = "/Volumes/Data/test/utf8-file-without-bom.txt";
public static void main(String[] args) throws IOException {
// (InputStream class implements Closeable)
// (Closeable interface extends AutoCloseable)
// try block will automatically close stream for you.
try (InputStream fileInputStream= new FileInputStream(file_path)) {
int code;
while((code = fileInputStream.read()) != -1) {
System.out.println(code +" " + (char)code);
}
} // end try
}
}
- Hướng dẫn và ví dụ Java Closeable
9. skip(long)
public long skip(long n) throws IOException
Phương thức skip(long) bỏ qua "n"bytes.
Phương thức này sẽ chặn (block) cho tới khi các bytes sẵn có hoặc xẩy ra lỗi IO, hoặc đã tiến tới cuối stream.
InputStream_skip_ex1.java
package org.o7planning.inputstream.ex;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class InputStream_skip_ex1 {
public static void main(String[] args) throws IOException {
String s = "123456789-987654321-ABCDE";
byte[] bytes = s.getBytes();
// ByteArrayInputStream is a subclass of InputStream.
InputStream is = new ByteArrayInputStream(bytes);
int firstByteCode = is.read();
int secondByteCode = is.read();
System.out.println("First byte: " + (char) firstByteCode);
System.out.println("Second byte: " + (char) secondByteCode);
is.skip(18); // Skips 18 bytes.
int code;
while ((code = is.read()) != -1) {
System.out.println(code +" " + (char) code);
}
is.close();
}
}
Output:
First byte: 1
Second byte: 2
65 A
66 B
67 C
68 D
69 E
10. transferTo(OutputStream)
// Java 10+
public long transferTo(OutputStream out) throws IOException
Phương thức transferTo(OutputStream) được sử dụng để đọc tất cả các bytes từ InputStream hiện tại và ghi chúng vào đối tượng OutputStream đã cho, và trả về số bytes đã chuyển sang OutputStream. Sau khi hoàn thành, đối tượng InputStream hiện tại sẽ ở cuối của stream. Phương thức này sẽ không đóng đối tượng InputStream hiện tại cũng như đối tượng OutputStream.
InputStream_transferTo_ex1.java
package org.o7planning.inputstream.ex;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class InputStream_transferTo_ex1 {
public static void main(String[] args) throws IOException {
String s = "123456789-987654321-ABCDE";
byte[] bytes = s.getBytes();
// ByteArrayInputStream is a subclass of InputStream.
InputStream reader = new ByteArrayInputStream(bytes);
// Or Windows path: C:/Somepath/out-file.txt
File file = new File("/Volumes/Data/test/out-file.txt");
// Create parent folder.
file.getParentFile().mkdirs();
OutputStream writer = new FileOutputStream(file);
reader.skip(10); // Skips 10 bytes.
reader.transferTo(writer);
reader.close();
writer.close();
}
}
Output:
out-file.txt
987654321-ABCDE
- OutputStream
- FileOutputStream
11. markSupported()
public boolean markSupported()
Phương thức markSupported() được sử dụng để kiểm tra đối tượng InputStream hiện tại có hỗ trợ hoạt động mark(int) hay không. (Xem thêm phương thức mark(int))
12. mark(int)
public void mark(int readAheadLimit) throws IOException
Phương thức mark(int) cho phép bạn đánh dấu vị trí hiện tại trên stream. Bạn có thể đọc tiếp các bytes tiếp theo, và gọi phương thức reset() để quay trở lại vị trí đã đánh dấu trước đó. Trong đó readAheadLimit là số bytes tối đa có thể đọc sau khi đánh dấu mà không làm mất vị trí đã đánh dấu.
Chú ý: Không phải tất cả các InputStream đều hỗ trợ hoạt động mark(int). Để chắc chắn bạn cần gọi phương thức markSupported() để kiểm tra xem đối tượng InputStream hiện tại có hỗ trợ hoạt động đó hay không.
InputStream_mark_ex1.java
package org.o7planning.inputstream.ex;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class InputStream_mark_ex1 {
public static void main(String[] args) throws IOException {
String s = "123456789-987654321-ABCDE";
byte[] bytes = s.getBytes(); // byte[]{'1','2', .... 'E'}
// ByteArrayInputStream is a subclass of InputStream.
InputStream is = new ByteArrayInputStream(bytes);
is.skip(10); // Skips 10 bytes.
System.out.println("ByteArrayInputStream markSupported? " + is.markSupported()); // true
is.mark(9);
int code1 = is.read();
int code2 = is.read();
System.out.println(code1 + " " + (char) code1); // '9'
System.out.println(code2 + " " + (char) code2); // '8'
is.skip(5);
System.out.println("Reset");
is.reset(); // Return to the marked position.
int code;
while((code = is.read())!= -1) {
System.out.println(code + " " + (char)code);
}
is.close();
}
}
Output:
ByteArrayInputStream markSupported? true
57 9
56 8
Reset
57 9
56 8
55 7
54 6
53 5
52 4
51 3
50 2
49 1
45 -
65 A
66 B
67 C
68 D
69 E
Các hướng dẫn Java IO
- Hướng dẫn và ví dụ Java CharArrayWriter
- Hướng dẫn và ví dụ Java FilterReader
- Hướng dẫn và ví dụ Java FilterWriter
- Hướng dẫn và ví dụ Java PrintStream
- Hướng dẫn và ví dụ Java BufferedReader
- Hướng dẫn và ví dụ Java BufferedWriter
- Hướng dẫn và ví dụ Java StringReader
- Hướng dẫn và ví dụ Java StringWriter
- Hướng dẫn và ví dụ Java PipedReader
- Hướng dẫn và ví dụ Java LineNumberReader
- Hướng dẫn và ví dụ Java PushbackReader
- Hướng dẫn và ví dụ Java PrintWriter
- Hướng dẫn sử dụng luồng vào ra nhị phân trong Java
- Hướng dẫn sử dụng luồng vào ra ký tự trong Java
- Hướng dẫn và ví dụ Java BufferedOutputStream
- Hướng dẫn và ví dụ Java ByteArrayOutputStream
- Hướng dẫn và ví dụ Java DataOutputStream
- Hướng dẫn và ví dụ Java PipedInputStream
- Hướng dẫn và ví dụ Java OutputStream
- Hướng dẫn và ví dụ Java ObjectOutputStream
- Hướng dẫn và ví dụ Java PushbackInputStream
- Hướng dẫn và ví dụ Java SequenceInputStream
- Hướng dẫn và ví dụ Java BufferedInputStream
- Hướng dẫn và ví dụ Java Reader
- Hướng dẫn và ví dụ Java Writer
- Hướng dẫn và ví dụ Java FileReader
- Hướng dẫn và ví dụ Java FileWriter
- Hướng dẫn và ví dụ Java CharArrayReader
- Hướng dẫn và ví dụ Java ByteArrayInputStream
- Hướng dẫn và ví dụ Java DataInputStream
- Hướng dẫn và ví dụ Java ObjectInputStream
- Hướng dẫn và ví dụ Java InputStreamReader
- Hướng dẫn và ví dụ Java OutputStreamWriter
- Hướng dẫn và ví dụ Java InputStream
- Hướng dẫn và ví dụ Java FileInputStream
Show More
- Hướng dẫn lập trình Java Servlet/JSP
- Các hướng dẫn Java New IO
- Các hướng dẫn Spring Cloud
- Các hướng dẫn Java Oracle ADF
- Các hướng dẫn Java Collections Framework
- Java cơ bản
- Các hướng dẫn Java Date Time
- Các thư viện mã nguồn mở Java
- Các hướng dẫn Java Web Services
- Các hướng dẫn Struts2 Framework
- Các hướng dẫn Spring Boot