Java - Luồng I/O: Hướng Dẫn Cho Người Mới Bắt Đầu

Xin chào các bạn, các nhà lập trình Java đầy kỳ niệm! Hôm nay, chúng ta sẽ bắt đầu hành trình thú vị vào thế giới Luồng I/O Java. Đừng lo nếu bạn hoàn toàn mới bắt đầu với lập trình – tôi sẽ là người hướng dẫn bạn, và chúng ta sẽ làm theo từng bước. Khi hết hướng dẫn này, bạn sẽ xử lý tệp và luồng như một chuyên gia!

Java - I/O Streams

Luồng I/O là gì?

Trước khi bước vào, hãy hiểu rõ luồng I/O là gì. Trong Java, một luồng là một chuỗi dữ liệu. Phần "I/O" đại diện cho Input/Output. Do đó, luồng I/O là cách Java xử lý việc đọc và ghi vào các nguồn khác nhau, như tệp, kết nối mạng, hoặc thậm chí là console.

Hãy tưởng tượng một luồng như là một con sông dữ liệu. Bạn có thể:

  1. Lấy nước (dữ liệu) ra khỏi con sông (luồng đầu vào)
  2. Đổ nước (dữ liệu) vào con sông (luồng đầu ra)

Luồng Tiêu Chuẩn

Java cung cấp ba luồng tiêu chuẩn mà đã được thiết lập sẵn:

  1. System.in (Luồng Đầu Vào)
  2. System.out (Luồng Đầu Ra)
  3. System.err (Luồng Lỗi Đầu Ra)

Hãy bắt đầu với một ví dụ đơn giản:

import java.util.Scanner;

public class HelloStream {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Tên bạn là gì? ");
String name = scanner.nextLine();
System.out.println("Xin chào, " + name + "!");
scanner.close();
}
}

Trong ví dụ này, chúng ta đang sử dụng System.in để đọc đầu vào từ người dùng, và System.out để hiển thị đầu ra. Lớp Scanner giúp chúng ta dễ dàng đọc từ luồng đầu vào.

Đọc và Ghi Tệp

Bây giờ, hãy chuyển sang một điều thú vị hơn – làm việc với tệp!

Đọc Từ Tệp

Dưới đây là cách bạn có thể đọc từ một tệp:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println("Đã xảy ra lỗi: " + e.getMessage());
}
}
}

Mã này đọc một tệp có tên "example.txt" từng dòng và in mỗi dòng ra console. Câu lệnh try-with-resources đảm bảo rằng tệp được đóng đúng sau khi chúng ta đọc xong.

Ghi Vào Tệp

Việc ghi vào tệp cũng rất dễ:

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class FileWriterExample {
public static void main(String[] args) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
writer.write("Hello, File I/O!");
writer.newLine();
writer.write("Đây là một dòng mới.");
} catch (IOException e) {
System.err.println("Đã xảy ra lỗi: " + e.getMessage());
}
}
}

Mã này tạo một tệp mới có tên "output.txt" và ghi hai dòng vào tệp đó.

FileOutputStream

Đôi khi, bạn có thể cần ghi dữ liệu nhị phân vào một tệp. Đó là nơi FileOutputStream có thể giúp ích:

import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamExample {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("binary.dat")) {
byte[] data = {65, 66, 67, 68, 69}; // Giá trị ASCII cho A, B, C, D, E
fos.write(data);
} catch (IOException e) {
System.err.println("Đã xảy ra lỗi: " + e.getMessage());
}
}
}

Ví dụ này ghi dữ liệu nhị phân vào một tệp có tên "binary.dat".

Điều Hướng Tệp và I/O

Java cung cấp lớp File để làm việc với đường dẫn tệp và thư mục. Dưới đây là một ví dụ:

import java.io.File;

public class FileNavigationExample {
public static void main(String[] args) {
File file = new File("example.txt");
System.out.println("Tệp tồn tại: " + file.exists());
System.out.println("Tên tệp: " + file.getName());
System.out.println("Đường dẫn tuyệt đối: " + file.getAbsolutePath());
}
}

Mã này minh họa cách lấy thông tin về tệp bằng cách sử dụng lớp File.

Thư Mục Trong Java

Việc làm việc với thư mục tương tự như làm việc với tệp. Hãy xem cách tạo một thư mục:

import java.io.File;

public class DirectoryExample {
public static void main(String[] args) {
File dir = new File("newDirectory");
if (dir.mkdir()) {
System.out.println("Thư mục đã được tạo thành công!");
} else {
System.out.println("Tạo thư mục thất bại.");
}
}
}

Mã này tạo một thư mục mới có tên "newDirectory" trong thư mục làm việc hiện tại.

Liệt Kê Thư Mục

Cuối cùng, hãy xem cách liệt kê nội dung của một thư mục:

import java.io.File;

public class ListDirectoryExample {
public static void main(String[] args) {
File dir = new File(".");
String[] fileList = dir.list();
if (fileList != null) {
for (String fileName : fileList) {
System.out.println(fileName);
}
} else {
System.out.println("Thư mục không tồn tại hoặc không phải là thư mục.");
}
}
}

Mã này liệt kê tất cả các tệp và thư mục trong thư mục hiện tại.

Kết Luận

Xin chúc mừng! Bạn đã bước ra đầu tiên vào thế giới Luồng I/O Java. Chúng ta đã trải qua nhiều khía cạnh, từ việc đọc/ghi cơ bản đến xử lý tệp và thư mục. Hãy nhớ, luyện tập sẽ làm bạn hoàn hảo, vì vậy đừng ngần ngại thử nghiệm các khái niệm này.

Dưới đây là bảng tóm tắt các phương thức mà chúng ta đã sử dụng:

Phương Thức Mô Tả
Scanner.nextLine() Đọc một dòng văn bản từ đầu vào
BufferedReader.readLine() Đọc một dòng văn bản từ tệp
BufferedWriter.write() Ghi một chuỗi vào tệp
BufferedWriter.newLine() Ghi một dấu phân đoạn dòng vào tệp
FileOutputStream.write() Ghi byte vào tệp
File.exists() Kiểm tra xem tệp có tồn tại không
File.getName() Lấy tên của tệp
File.getAbsolutePath() Lấy đường dẫn tuyệt đối của tệp
File.mkdir() Tạo thư mục
File.list() Liệt kê nội dung của thư mục

Hãy tiếp tục lập trình, học hỏi, và quan trọng nhất, hãy vui vẻ! Nhớ rằng, mọi chuyên gia đều từng là người mới bắt đầu. Chúc mừng lập trình!

Credits: Image by storyset