Luồng Ký tự
(Character Streams)

Luồng Ký tự (Character Streams) trong Java được sử dụng để đọc và ghi dữ liệu ký tự (Unicode). Chúng tự động xử lý việc chuyển đổi giữa mã hóa ký tự nội bộ của Java (Unicode) và mã hóa ký tự địa phương. Điều này giúp đơn giản hóa quá trình xử lý văn bản và hỗ trợ tốt hơn cho quốc tế hóa.

Dữ liệu ký tự là dữ liệu được biểu diễn dưới dạng các ký tự Unicode. Mỗi ký tự có thể chiếm 2 byte (16 bit) trong bộ nhớ vì Java sử dụng bảng mã Unicode, có thể biểu diễn mọi ký tự từ bất kỳ ngôn ngữ nào.

Tất cả các lớp luồng ký tự đều kế thừa từ hai lớp gốc là Reader và Write. Có nhiều lớp luồng ký tự khác nhau. Ví dụ điển hình để minh họa hoạt động của luồng ký tự là các lớp FileReader và FileWriter chuyên dùng cho thao tác đọc/ghi dữ liệu dạng ký tự từ một file, BufferedReader và BufferedWriter được sử dụng để đọc/ghi dữ liệu dạng ký tự với bộ nhớ đệm. Các loại luồng ký tự khác hoạt động tương tự, chủ yếu khác nhau về cách tạo. Bây giờ Chúng ta sẽ khám phá chi tiết từng lớp trong luồng ký tự trong Java, bao gồm các lớp chính được sử dụng để thực hiện các hoạt động đầu vào và đầu ra liên quan đến dữ liệu ký tự.

I/O theo dòng (Line-Oriented I/O)

I/O theo Dòng (Line-Oriented I/O) trong Java là một cách xử lý dữ liệu ký tự tập trung vào việc đọc và ghi từng dòng thay vì từng ký tự đơn lẻ.

Dòng là một chuỗi ký tự kết thúc bằng một ký tự xuống dòng, còn được gọi là line terminator.

Ký tự xuống dòng có thể khác nhau tùy theo hệ điều hành:

↳ Windows: \r\n (CRLF) - Carriage Return + Line Feed.

↳ macOS cũ: \r (CR) - Carriage Return.

↳ Unix/Linux/macOS mới: \n (LF) - Line Feed.

Việc hỗ trợ các ký tự xuống dòng khác nhau là quan trọng để đảm bảo rằng các tệp văn bản được đọc và ghi chính xác trên nhiều hệ điều hành khác nhau.

Trong Java, Reader và Writer là hai lớp trừu tượng (abstract class) quan trọng trong gói java.io, đóng vai trò nền tảng cho các hoạt động đọc và ghi dữ liệu ký tự. Chúng cung cấp một giao diện chung giúp bạn có thể dễ dàng tương tác với nhiều loại nguồn và đích dữ liệu khác nhau, như tệp, mảng ký tự, chuỗi, hoặc thậm chí các luồng mạng.

Lớp Trừu Tượng Reader (Abstract Class Reader)

Lớp Reader trong Java là một lớp trừu tượng nằm trong gói java.io, đại diện cho một luồng đọc ký tự (character stream). Lớp này cung cấp các phương thức cơ bản để đọc ký tự, mảng ký tự, hoặc các dòng văn bản từ các nguồn khác nhau như tệp, chuỗi, hoặc luồng nhập xuất. Vì Reader là một lớp trừu tượng, bạn không thể khởi tạo nó trực tiếp, mà phải sử dụng các lớp con cụ thể của nó để đọc dữ liệu từ các nguồn cụ thể.

Các lớp con phải cài đặt ít nhất hai phương thức: read(char[], int, int) và close().

Cú pháp khai báo lớp trừu tượng Reader

Cú pháp

public abstract class Reader
extends Object
implements Readable, Closeable

Dưới đây là giải thích chi tiết về cú pháp khai báo này:

↳ public: Từ khóa public chỉ ra rằng lớp Reader có thể được truy cập từ bất kỳ đâu trong chương trình, nghĩa là nó có thể được sử dụng bởi các lớp và gói khác.

↳ abstract: Lớp Reader được khai báo là lớp trừu tượng. Điều này có nghĩa là bạn không thể tạo một đối tượng trực tiếp từ lớp này, mà phải kế thừa nó và triển khai các phương thức cụ thể trong lớp con. Lớp trừu tượng có thể chứa các phương thức trừu tượng (chưa được định nghĩa) và phương thức thông thường (đã được định nghĩa).

↳ class Reader: Từ khóa class chỉ ra rằng Reader là một lớp trong Java. Đây là một lớp trừu tượng cung cấp các phương thức chung để đọc dữ liệu ký tự.

↳ extends Object: Lớp Reader kế thừa từ lớp Object, lớp cha của mọi lớp trong Java. Mọi lớp trong Java mặc định đều kế thừa từ Object nếu không có lớp cha nào khác được chỉ định. Điều này có nghĩa là lớp Reader cũng thừa hưởng các phương thức cơ bản của Object như toString(), equals(), và hashCode().

Lớp Reader thực hiện (implements) các giao diện Readable và Closeable. Khi một lớp thực hiện một giao diện, nó phải cung cấp định nghĩa cho tất cả các phương thức trừu tượng trong giao diện đó, trừ khi lớp đó là một lớp trừu tượng (như trong trường hợp này).

↳ implements Readable: Là một giao diện trong Java với một phương thức duy nhất là read(CharBuffer cb). Nó cho phép một lớp thực hiện khả năng đọc dữ liệu vào một đối tượng CharBuffer.

↳ implements Closeable: Một giao diện trong Java với phương thức close().Bất kỳ lớp nào thực hiện giao diện này phải cung cấp một cơ chế để đóng tài nguyên khi không còn sử dụng nữa, giúp ngăn ngừa rò rỉ tài nguyên.

Trường của lớp trừu tượng Reader

Lớp Reader chỉ có một trường duy nhất. Trường lock được sử dụng để đảm bảo rằng chỉ một luồng có thể truy cập vào luồng ký tự tại một thời điểm, tránh các vấn đề đồng bộ hóa.

↳ protected Object lock: Một đối tượng được sử dụng để đồng bộ hóa các hoạt động trên luồng này.

Các constructor của lớp trừu tượng Reader

Lớp Reader có hai constructor chính để tạo đối tượng. Lớp Reader là một lớp trừu tượng, nên các constructor của nó được khai báo với quyền truy cập protected:

↳ protected Reader(): Tạo một đối tượng Reader mới với các phần đồng bộ hóa được thực hiện trên chính đối tượng Reader.

↳ protected Reader(Object lock): Tạo một đối tượng Reader mới với các phần đồng bộ hóa được thực hiện trên đối tượng lock được truyền vào.

Các phương thức của lớp trừu tượng Reader

Các phương thức của lớp Reader trong Java cung cấp chức năng cơ bản để đọc dữ liệu từ luồng đầu vào, từ đọc một ký tự đơn lẻ đến đọc nhiều ký tự cùng lúc. Ngoài ra, còn có các phương thức để đánh dấu vị trí trong luồng, bỏ qua dữ liệu, và đóng luồng sau khi sử dụng. Dưới đây là danh sách tất cả các phương thức của lớp Reader trong Java:

↳ abstract void close(): Đóng luồng và giải phóng tài nguyên.

↳ void mark(int readAheadLimit): Đánh dấu vị trí hiện tại trong luồng.

↳ boolean markSupported(): Kiểm tra xem luồng hỗ trợ đánh dấu hay không.

↳ int read(): Đọc một ký tự.

↳ int read(char[] cbuf): Đọc nhiều ký tự vào mảng cbuf.

↳ abstract int read(char[] cbuf, int off, int len): Đọc một phần của mảng cbuf với độ dài len bắt đầu từ vị trí off.

↳ int read(CharBuffer target): Đọc ký tự vào một CharBuffer.

↳ boolean ready(): Kiểm tra xem luồng sẵn sàng để đọc hay không.

↳ void reset(): Đặt lại vị trí của luồng về vị trí đã đánh dấu.

↳ long skip(long n): Bỏ qua n ký tự.

Các lớp con kế thừa trực tiếp từ lớp trừu tượng Reader trong Java

Các lớp con của Reader mở rộng khả năng đọc dữ liệu từ nhiều nguồn khác nhau, cung cấp sự linh hoạt trong việc xử lý đầu vào. Dưới đây là danh sách các lớp con và các lớp liên quan đến Reader, cùng với mô tả ngắn gọn về từng lớp:

↳ BufferedReader: Đọc dữ liệu ký tự từ một luồng với bộ đệm, tăng hiệu suất đọc.

↳ LineNumberReader: Kế thừa từ BufferedReader, thêm khả năng đếm số dòng khi đọc.

↳ InputStreamReader: Chuyển đổi luồng byte thành luồng ký tự, thường dùng để đọc dữ liệu từ file hoặc mạng.

↳ FileReader: Đọc dữ liệu ký tự từ một file.

↳ CharArrayReader: Đọc dữ liệu ký tự từ một mảng ký tự.

↳ FilterReader: Lớp trừu tượng, là lớp cơ sở cho các lớp lọc luồng ký tự.

↳ PushbackReader: Kế thừa từ FilterReader, cho phép đẩy một ký tự vừa đọc trở lại luồng để đọc lại.

↳ PipedReader: Dùng để truyền dữ liệu ký tự giữa hai luồng thông qua một ống dẫn.

↳ StringReader: Đọc dữ liệu ký tự từ một chuỗi.

Các lớp con kế thừa từ Reader trong Java - minh họa
Ảnh mô tả các lớp con kế thừa trực tiếp từ lớp trừu tượng Reader.

Câu Nói Truyền Cảm Hứng

“Không ai sinh ra đã giỏi. Mọi thành công đều bắt đầu từ một bước nhỏ.” – Lao Tzu

Không Gian Tích Cực

“Chúc bạn một ngày mới đầy năng lượng và sự sáng tạo, luôn tiến về phía trước.”