Luồng Chuẩn
(Standard Streams)
Các chương trình Java thường được chạy từ dòng lệnh và tương tác với người dùng trong môi trường dòng lệnh. Java hỗ trợ tương tác này theo hai cách: thông qua luồng chuẩn (Standard Streams) và giao diện điều khiển (Console).
Luồng Chuẩn (Standard Streams)
Luồng Chuẩn (Standard Streams) là một tính năng có trong nhiều hệ điều hành, cho phép chương trình mặc định đọc dữ liệu từ bàn phím và ghi dữ liệu ra màn hình. Ngoài ra, chúng còn hỗ trợ I/O trên tệp và giữa các chương trình, mặc dù tính năng này thường được điều khiển bởi trình thông dịch dòng lệnh, không phải bởi chương trình.
Nền tảng Java hỗ trợ ba luồng chuẩn (Standard Streams):
↳ Standard Input (Đầu vào chuẩn): Được truy cập qua System.in, luồng này đọc dữ liệu từ bàn phím.
↳ Standard Output (Đầu ra chuẩn): Được truy cập qua System.out, luồng này ghi dữ liệu ra màn hình.
↳ Standard Error (Lỗi chuẩn): Được truy cập qua System.err, luồng này được dùng để ghi thông báo lỗi, cho phép xử lý đầu ra lỗi riêng biệt với đầu ra thông thường.
Các đối tượng này được hệ thống tự động định nghĩa và không cần phải mở thủ công. Mặc dù cả System.out và System.err đều dùng để xuất dữ liệu, việc giữ chúng riêng biệt giúp người dùng có thể chuyển hướng đầu ra thông thường sang tệp trong khi vẫn có thể xem được các thông báo lỗi trên màn hình.
Luồng byte và luồng ký tự
Mặc dù có thể bạn mong đợi, nhưng các Luồng Chuẩn trong Java không phải là luồng ký tự mà là luồng byte. Cụ thể:
↳ System.out và System.err là các đối tượng của PrintStream, về mặt kỹ thuật là luồng byte. Tuy nhiên, PrintStream sử dụng một luồng ký tự nội bộ để mô phỏng nhiều tính năng của luồng ký tự, chẳng hạn như tự động chuyển đổi các kiểu dữ liệu.
↳ System.in là một đối tượng của InputStream và là một luồng byte thuần túy, không có hỗ trợ tích hợp cho các tính năng của luồng ký tự. Để sử dụng System.in như một luồng ký tự, bạn cần gói nó trong InputStreamReader, giúp chuyển đổi đầu vào byte thành ký tự.
Ví Dụ
InputStreamReader input = new InputStreamReader(System.in);
Điều này cho phép bạn đọc các ký tự từ đầu vào chuẩn, giúp dễ dàng xử lý dữ liệu dạng văn bản trong một chương trình Java.
Ví dụ 1
Dưới đây là một ví dụ sử dụng System.in với InputStreamReader để đọc dữ liệu từ bàn phím. InputStreamReader chuyển đổi byte stream từ System.in thành character stream, giúp chúng ta có thể đọc ký tự hoặc chuỗi từ bàn phím.
Ví dụ: Example.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Example {
public static void main(String[] args) {
// Tạo đối tượng InputStreamReader để đọc dữ liệu từ System.in
InputStreamReader reader = new InputStreamReader(System.in);
// Gói InputStreamReader trong BufferedReader để đọc từng dòng văn bản
BufferedReader bufferedReader = new BufferedReader(reader);
try {
// In ra thông báo yêu cầu người dùng nhập dữ liệu
System.out.print("Nhập tên của bạn: ");
// Đọc dữ liệu từ bàn phím
String name = bufferedReader.readLine();
// In ra dữ liệu người dùng đã nhập
System.out.println("Chào, " + name + "!");
} catch (IOException e) {
// Xử lý ngoại lệ nếu xảy ra lỗi khi đọc dữ liệu
System.err.println("Đã xảy ra lỗi khi đọc dữ liệu: " + e.getMessage());
}
}
}
Kết quả của chương trình là
Chào, duong!
Khi chạy chương trình, nó sẽ yêu cầu người dùng nhập tên. Sau khi người dùng nhập tên và nhấn Enter, chương trình sẽ in ra dòng chữ chào mừng bao gồm tên mà người dùng đã nhập.
Ví dụ 2
Dưới đây là một ví dụ sử dụng Scanner để đọc dữ liệu từ bàn phím. Scanner là một lớp tiện ích trong Java giúp đọc dữ liệu từ các nguồn khác nhau, bao gồm System.in, một cách dễ dàng hơn.
Ví dụ: Example.java
import java.util.Scanner;
public class Example {
public static void main(String[] args) {
// Tạo đối tượng Scanner để đọc dữ liệu từ System.in
Scanner scanner = new Scanner(System.in);
// In ra thông báo yêu cầu người dùng nhập dữ liệu
System.out.print("Nhập tên của bạn: ");
// Đọc dữ liệu từ bàn phím
String name = scanner.nextLine();
// In ra dữ liệu người dùng đã nhập
System.out.println("Chào, " + name + "!");
// Đóng đối tượng Scanner
scanner.close();
}
}
Kết quả của chương trình là
Chào, ABC!
Khi chạy chương trình, nó sẽ yêu cầu người dùng nhập tên. Sau khi người dùng nhập tên và nhấn Enter, chương trình sẽ in ra dòng chữ chào mừng bao gồm tên mà người dùng đã nhập.
Ví dụ 3
Dưới đây là một ví dụ minh họa cách sử dụng cả System.out và System.err trong cùng một lớp để in thông tin và thông báo lỗi.
Ví dụ: Example.java
public class Example {
public static void main(String[] args) {
System.out.println("Chương trình bắt đầu.");
try {
// Giả định có một lỗi khi thực hiện phép chia cho 0
int result = 10 / 0;
System.out.println("Kết quả: " + result);
} catch (ArithmeticException e) {
// In thông báo lỗi ra luồng System.err
System.err.println("Lỗi: Không thể chia cho 0.");
}
System.out.println("Chương trình kết thúc.");
}
}
Kết quả của chương trình là
Lỗi: Không thể chia cho 0.
Chương trình kết thúc.
Trong trường hợp này, thông báo lỗi sẽ được in ra màn hình nhưng có thể được xử lý khác biệt nếu bạn chuyển hướng luồng System.err sang một file khác hoặc một nơi khác, giúp tách biệt giữa thông tin thông thường và thông báo lỗi.