Xem thêm

Gói java.io: Giới thiệu về Input và Output trong Java

Huy Erick
Gói java.io chứa các lớp cần thiết để thực hiện Input và Output (I/O) trong Java. Nó cung cấp các stream để đại diện cho nguồn input và đích output. Các stream này hỗ trợ...

Gói java.io chứa các lớp cần thiết để thực hiện Input và Output (I/O) trong Java. Nó cung cấp các stream để đại diện cho nguồn input và đích output. Các stream này hỗ trợ nhiều loại dữ liệu như các kiểu gốc, Object, các ký tự nội bộ và nhiều hơn nữa.

Byte Stream trong Java

Byte Stream trong Java được sử dụng để thực hiện Input và Output của byte (8 bit). Lớp FileInputStream và FileOutputStream là hai lớp phổ biến nhất trong Byte Stream. Dưới đây là một ví dụ sử dụng hai lớp này để sao chép một file input vào một file output:

import java.io.*;

public class CopyFile {
    public static void main(String args[]) throws IOException {
        FileInputStream in = null;
        FileOutputStream out = null;

        try {
            in = new FileInputStream("input.txt");
            out = new FileOutputStream("output.txt");

            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
        } finally {
            if (in != null) {
                in.close();
            }

            if (out != null) {
                out.close();
            }
        }
    }
}

Hãy giả sử chúng ta có một file có nội dung sau:

Day la vi du ve sao chep file.

Sau đó, biên dịch và thực thi chương trình trên, sẽ tạo ra một file có nội dung giống như file input. Để thực hiện điều này, hãy đặt code trên vào trong file CopyFile.java và thực hiện các bước sau:

$javac CopyFile.java
$java CopyFile

Character Stream trong Java

Character Stream trong Java được sử dụng để thực hiện Input và Output của Unicode 16 bit, trong khi Byte Stream chỉ hỗ trợ byte (8 bit). Lớp FileReader và FileWriter là hai lớp thông dụng trong Character Stream. Mặc dù FileReader sử dụng FileInputStream và FileWriter sử dụng FileOutputStream, nhưng có một điểm khác biệt quan trọng là FileReader đọc hai byte cùng một lúc và FileWriter ghi 2 byte cùng một lúc.

Chúng ta có thể viết lại ví dụ trước sử dụng hai lớp này để sao chép một file input (chứa các ký tự Unicode) vào một file output:

import java.io.*;

public class CopyFile {
    public static void main(String args[]) throws IOException {
        FileReader in = null;
        FileWriter out = null;

        try {
            in = new FileReader("input.txt");
            out = new FileWriter("output.txt");

            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
        } finally {
            if (in != null) {
                in.close();
            }

            if (out != null) {
                out.close();
            }
        }
    }
}

Giả sử chúng ta có file input có nội dung sau:

Day la vi du ve sao chep file.

Tiếp theo, biên dịch và thực thi chương trình trên, kết quả sẽ là một file output có cùng nội dung như file input. Để thực hiện điều này, hãy đặt code trên vào trong file CopyFile.java và thực hiện các bước sau:

$javac CopyFile.java
$java CopyFile

Stream Chuẩn trong Java

Tất cả các ngôn ngữ lập trình đều cung cấp hỗ trợ cho Input và Output chuẩn. Trong Java, có 3 Stream Chuẩn là STDIN, STDOUT và STDERR, tương ứng với đầu vào chuẩn, đầu ra chuẩn và lỗi chuẩn. Chúng được biểu diễn như System.in, System.out và System.err.

Dưới đây là một chương trình đơn giản sử dụng InputStreamReader để đọc dữ liệu từ đầu vào chuẩn cho đến khi người dùng gõ phím "q":

import java.io.*;

public class ReadConsole {
    public static void main(String args[]) throws IOException {
        InputStreamReader cin = null;

        try {
            cin = new InputStreamReader(System.in);
            System.out.println("Nhap cac ky tu, 'q' de thoat.");

            char c;
            do {
                c = (char) cin.read();
                System.out.print(c);
            } while(c != 'q');
        } finally {
            if (cin != null) {
                cin.close();
            }
        }
    }
}

Giữ code trên trong file ReadConsole.java và thực thi và biên dịch nó như dưới đây. Chương trình này tiếp tục đọc và hiển thị kết quả cho đến khi chúng ta nhấn phím "q".

$javac ReadConsole.java
$java ReadConsole
Nhap cac ky tu, 'q' de thoat.
1
1
e
e
q
q

Đọc và Ghi File trong Java

InputStream được sử dụng để đọc dữ liệu từ một nguồn, trong khi OutputStream được sử dụng để ghi dữ liệu tới một đích. Dưới đây là một cấu trúc tổ chức của các lớp để xử lý Input và Output:

Java I/O Streams

Hai luồng quan trọng nhất là FileInputStream và FileOutputStream, chúng sẽ được bàn luận sau.

FileInputStream trong Java

Lớp FileInputStream được sử dụng để đọc dữ liệu từ các file. Đối tượng FileInputStream có thể được tạo bằng cách sử dụng từ khóa new và một số kiểu constructor có sẵn.

Có hai constructor mà có thể được sử dụng để tạo một đối tượng FileInputStream trong Java. Constructor đầu tiên nhận tên file là một chuỗi để tạo một đối tượng Input Stream để đọc file:

InputStream f = new FileInputStream("C:/java/hello");

Constructor thứ hai nhận một đối tượng File để tạo một đối tượng Input Stream để đọc file. Đầu tiên chúng ta tạo một đối tượng File bằng cách sử dụng phương thức File() như sau:

File f = new File("C:/java/hello");
InputStream f = new FileInputStream(f);

Khi chúng ta có đối tượng InputStream này, có một số phương thức có thể được sử dụng để đọc stream hoặc thực hiện các hoạt động khác trên stream này.

FileOutputStream trong Java

Lớp FileOutputStream được sử dụng để tạo một file và ghi dữ liệu vào trong nó. Luồng này sẽ tạo file nếu nó chưa tồn tại trước khi mở nó để ghi output.

Có hai constructor mà có thể được sử dụng để tạo một đối tượng FileOutputStream trong Java. Constructor đầu tiên nhận tên file là một chuỗi để tạo một đối tượng Output Stream để ghi file:

OutputStream f = new FileOutputStream("C:/java/hello")

Constructor thứ hai nhận một đối tượng File để tạo một đối tượng Output Stream để ghi file:

File f = new File("C:/java/hello");
OutputStream f = new FileOutputStream(f);

Khi bạn có đối tượng OutputStream này, có một số phương thức có thể được sử dụng để ghi stream hoặc thực hiện các hoạt động khác trên stream này.

Ví dụ

Dưới đây là một ví dụ đơn giản minh họa việc sử dụng InputStream và OutputStream:

import java.io.*;

public class fileStreamTest {
    public static void main(String args[]) {
        try {
            byte bWrite [] = {11,21,3,40,5};
            OutputStream os = new FileOutputStream("test.txt");

            for(int x=0; x < bWrite.length ; x++){
                os.write( bWrite[x] ); // ghi các byte vào stream
            }

            os.close();

            InputStream is = new FileInputStream("test.txt");
            int size = is.available();

            for(int i=0; i < size; i++){
                System.out.print((char)is.read() + " ");
            }

            is.close();
        } catch(IOException e) {
            System.out.print("Exception");
        }       
    }
}

Chương trình trên tạo một file test.txt và ghi các số đã cho dưới dạng nhị phân. Kết quả cũng được hiển thị trên stdout.

Điều hướng file và I/O trong Java

Có một số lớp khác cần được tìm hiểu để hiểu các khái niệm cơ bản về Điều hướng file và I/O.

  • Lớp File trong Java: Được sử dụng để tạo và quản lý các file và thư mục.
  • Lớp FileReader trong Java: Được sử dụng để đọc dữ liệu từ một file.
  • Lớp FileWriter trong Java: Được sử dụng để ghi dữ liệu vào một file.

Thư mục trong Java

Một thư mục là một File có thể chứa danh sách các file và thư mục khác. Bạn có thể sử dụng đối tượng File để tạo các thư mục và liệt kê các file có sẵn trong một thư mục. Để biết thêm chi tiết, bạn có thể xem các phương thức có thể được gọi trên đối tượng File và các khái niệm liên quan đến thư mục.

Tạo thư mục trong Java

Có hai phương thức tiện ích trong File để tạo một thư mục: mkdir() và mkdirs(). Phương thức mkdir() tạo một thư mục và trả về true nếu thành công và false nếu không. Phương thức mkdirs() được sử dụng để tạo cả một thư mục và các thư mục cha của nó.

Ví dụ sau tạo thư mục /tmp/user/java/bin:

import java.io.File;

public class CreateDir {
    public static void main(String args[]) {
        String dirname = "/tmp/user/java/bin";
        File d = new File(dirname);
        d.mkdirs();
    }
}

Liệt kê thư mục trong Java

Bạn có thể sử dụng phương thức list() của đối tượng File để liệt kê tất cả các file và thư mục có sẵn trong một thư mục:

import java.io.File;

public class ReadDir {
    public static void main(String[] args) {
        File file = null;
        String[] paths;

        try {
            file = new File("/tmp");
            paths = file.list();

            for(String path : paths) {
                System.out.println(path);
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

Kết quả sẽ hiển thị các file và thư mục có sẵn trong thư mục /tmp của bạn:

test1.txt
test2.txt
ReadDir.java
ReadDir.class

Trên đây là một số khái niệm cơ bản về Input và Output trong Java. Chúng ta đã tìm hiểu về Byte Stream, Character Stream, Stream Chuẩn, Đọc và Ghi File, Điều hướng file và thao tác với thư mục. Các khái niệm này là quan trọng và cần thiết khi làm việc với I/O trong Java.

1