Hướng dẫn và ví dụ Java Reader
1. Reader
Reader 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 ký tự (stream of characters) có được khi đọc một nguồn dữ liệu nào đó, chẳng hạn file văn bản.
public abstract class Reader implements Readable, Closeable
Về cơ bản bạn không thể sử dụng lớp Reader 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 tình huống đọc một file văn bản với mã hoá UTF-8:
utf-8-file.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.
FileReader là một lớp con của Reader thường được sử dụng để đọc các file văn bản và chúng ta sẽ nhận được một dòng chảy các ký tự (stream of characters). Bằng một cách nào đó các ký tự UTF-8 sẽ được chuyển đổi thành các ký tự của Java.
Chú ý: Kiểu char (Ký tự) trong Java có kích thước 2 bytes. Như vậy các ký tự trên FileReader là các ký tự có kích thước 2 bytes.
Xem thêm giải thích của tôi về cách Java chuyển đổi các ký tự UTF-8 thành các ký tự Java:
Reader Methods
public static Reader nullReader()
public int read(java.nio.CharBuffer target) throws IOException
public int read() throws IOException
public int read(char cbuf[]) throws IOException
public int read(char cbuf[], int off, int len) throws IOException
public long skip(long n) throws IOException
public boolean ready() throws IOException
public boolean markSupported()
public void mark(int readAheadLimit) throws IOException
public void reset() throws IOException
public void close() throws IOException
public long transferTo(Writer out) throws IOException
2. read()
public int read() throws IOException
Phương thức read() được sử dụng để đọc một ký tự, nó trả về mã số của ký tự vừa đọc được (Là một số nguyên trong khoảng 0 đến 65535), hoặc trả về -1 nếu đã tiến tới cuối stream (dòng chẩy).
Phương thức này sẽ chặn (block) cho tới khi ký tự sẵn có hoặc xẩy ra lỗi IO, hoặc đã tiến tới cuối stream.
Ví dụ:
Reader_read_ex1.java
package org.o7planning.reader.ex;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
public class Reader_read_ex1 {
public static void main(String[] args) throws IOException {
// StringReader is a subclass of Reader.
Reader reader = new StringReader("JP日本-八洲");
int charCode;
while((charCode = reader.read()) != -1) {
System.out.println((char)charCode + " " + charCode);
}
reader.close();
}
}
Output:
J 74
P 80
日 26085
本 26412
- 45
八 20843
洲 27954
3. read(char[])
public int read(char[] cbuf) throws IOException
Phương thức read(char[]) đọc các ký tự và gán vào các phần tử của mảng và trả về số ký tự 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 ký tự sẵn 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(char[]) 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.
Reader_read_ex1.java
package org.o7planning.reader.ex;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
public class Reader_read_ex2 {
public static void main(String[] args) throws IOException {
// StringReader is a subclass of Reader.
Reader reader = new StringReader("123456789-987654321-12345");
// Create a temporary char array.
char[] temp = new char[10];
int charCount = -1;
while ((charCount = reader.read(temp)) != -1) {
String s = new String(temp, 0, charCount);
System.out.println(s);
}
reader.close();
}
}
Output:
123456789-
987654321-
12345
4. read(char[], int, int)
public int read(char[] cbuf, int offset, int len) throws IOException
Phương thức read(char[],int,int) đọc các ký tự 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ố ký tự 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 ký tự sẵn có hoặc xẩy ra lỗi IO, hoặc đã tiến tới cuối stream.
5. read(java.nio.CharBuffer)
public int read(java.nio.CharBuffer target) throws IOException
Phương thức read(CharBuffer) được sử dụng để đọc các ký tự vào một đối tượng CharBufffer, và trả về số ký tự đọc được từ stream hoặc trả về -1 nếu đã tiến tới cuối của stream.
Phương thức này sẽ chặn (block) cho tới khi các ký tự sẵn có hoặc xẩy ra lỗi IO, hoặc đã tiến tới cuối stream.
Reader_read_ex3.java
package org.o7planning.reader.ex;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.nio.CharBuffer;
public class Reader_read_ex3 {
public static void main(String[] args) throws IOException {
// StringReader is a subclass of Reader.
Reader reader = new StringReader("123456789-987654321-12345");
CharBuffer cb = CharBuffer.allocate(10);
// Read for the first time
reader.read(cb);
System.out.println(cb.flip().toString());
// Read for the second time
reader.read(cb);
System.out.println(cb.flip().toString());
// Read for the third time.
reader.read(cb);
System.out.println(cb.flip().toString());
reader.close();
}
}
Output:
123456789-
987654321-
12345
- Hướng dẫn và ví dụ Java CharBuffer
6. 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(), ready(), 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 Reader 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().
Reader_close_ex1.java
package org.o7planning.reader.ex;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class Reader_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 {
// (Reader class implements Closeable)
// (Closeable interface extends AutoCloseable)
// try block will automatically close stream for you.
try (Reader fileReader= new FileReader(file_path)) {
int code;
while((code = fileReader.read()) != -1) {
System.out.println((char)code);
}
} // end try
}
}
- Hướng dẫn và ví dụ Java Closeable
7. skip(long)
public long skip(long n) throws IOException
Phương thức skip(long) bỏ qua "n" ký tự.
Phương thức này sẽ chặn (block) cho tới khi các ký tự sẵn có hoặc xẩy ra lỗi IO, hoặc đã tiến tới cuối stream.
Reader_skip_ex1.java
package org.o7planning.reader.ex;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
public class Reader_skip_ex1 {
public static void main(String[] args) throws IOException {
// StringReader is a subclass of Reader.
Reader reader = new StringReader("123456789-987654321-ABCDE");
int firstCharCode = reader.read();
int secondCharCode = reader.read();
System.out.println("First character: " + (char) firstCharCode);
System.out.println("Second character: " + (char) secondCharCode);
reader.skip(18); // Skips 18 characters.
int code;
while ((code = reader.read()) != -1) {
System.out.println((char) code);
}
reader.close();
}
}
Output:
First character: 1
Second character: 2
A
B
C
D
E
8. transferTo(Writer)
// Java 10+
public long transferTo(Writer out) throws IOException
Phương thức transferTo(Writer) được sử dụng để đọc tất cả các ký tự từ Reader hiện tại và ghi chúng vào đối tượng Writer đã cho, và trả về số ký tự đã chuyển sang Writer. Sau khi hoàn thành, đối tượng Reader hiện tại sẽ ở cuối của stream. Phương thức này sẽ không đóng đối tượng Reader hiện tại cũng như đối tượng Writer.
Reader_transferTo_ex1.java
package org.o7planning.reader.ex;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
public class Reader_transferTo_ex1 {
public static void main(String[] args) throws IOException {
// StringReader is a subclass of Reader.
Reader reader = new StringReader("123456789-987654321-ABCDE");
// Or Windows path: C:/Somepath/out-file.txt
File file = new File("/Volumes/Data/test/out-file.txt");
// Create parent folder.
file.getParentFile().mkdirs();
Writer writer = new FileWriter(file);
reader.skip(10); // Skips 10 characters.
reader.transferTo(writer);
reader.close();
writer.close();
}
}
Output:
out-file.txt
987654321-ABCDE
9. markSupported()
public boolean markSupported()
Phương thức markSupported() được sử dụng để kiểm tra đối tượng Reader hiện tại có hỗ trợ hoạt động mark(int) hay không. (Xem thêm phương thức mark(int))
Reader | markSupported()? |
StringReader | true |
CharArrayReader | true |
BufferedReader | true |
LineNumberReader | true |
FilterReader | true or false |
InputStreamReader | false |
FileReader | false |
PushbackReader | false |
10. 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 ký tự 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ố lượng ký tự 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 Reader đề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 Reader hiện tại có hỗ trợ hoạt động đó hay không.
Reader_mark_ex1.java
package org.o7planning.reader.ex;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
public class Reader_mark_ex1 {
public static void main(String[] args) throws IOException {
// StringReader is a subclass of Reader.
Reader reader = new StringReader("123456789-987654321-ABCDE");
reader.skip(10); // Skips 10 characters.
System.out.println("StringReader markSupported? " + reader.markSupported()); // true
reader.mark(9);
int code1 = reader.read();
int code2 = reader.read();
System.out.println((char) code1); // '9'
System.out.println((char) code2); // '8'
reader.skip(5);
System.out.println("Reset");
reader.reset(); // Return to the marked position.
int code;
while((code = reader.read())!= -1) {
System.out.println((char)code);
}
reader.close();
}
}
Output:
StringReader markSupported? true
9
8
Reset
9
8
7
6
5
4
3
2
1
-
A
B
C
D
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