1. OutputStreamlớp học

Gần đây chúng tôi đã khám phá các luồng đầu vào. Đã đến lúc nói về luồng đầu ra.

Lớp này OutputStreamlà lớp cha cho tất cả các lớp hỗ trợ đầu ra byte. Đây là một lớp trừu tượng không tự làm gì, nhưng nó có các lớp con cho mọi trường hợp.

Nghe có vẻ vô cùng phức tạp. Nói một cách đơn giản hơn, lớp này hoạt động trên byte chứ không phải ký tự hoặc các loại dữ liệu khác chẳng hạn. Và thực tế là nó trừu tượng có nghĩa là chúng ta thường không sử dụng nó, mà là một trong những lớp hậu duệ của nó. Ví dụ, FileOutputStreamvà như thế.

Nhưng trở lại OutputStreamlớp học. Lớp này có các phương thức mà tất cả các lớp con của nó phải thực hiện. Dưới đây là những cái chính:

phương pháp Sự miêu tả
void write(int b)
Ghi một byte (không phải là int) vào luồng.
void write(byte[] buffer)
Ghi một mảng byte vào luồng
void write(byte[] buffer, off, len)
Ghi một phần của mảng byte vào luồng
void flush()
Ghi tất cả dữ liệu được lưu trữ trong bộ đệm vào luồng
void close()
Đóng luồng

Khi bạn tạo một đối tượng của một lớp kế thừa InputStream, bạn thường chỉ định một đối tượng nguồn để InputStreamđọc dữ liệu từ đó. Khi bạn tạo một đối tượng của lớp kế thừa OutputStream, bạn cũng thường chỉ định đối tượng hoặc luồng đích mà dữ liệu sẽ được ghi vào.

Chúng ta hãy xem qua tất cả các phương thức của lớp OutputStream:

write(int b)phương pháp

Phương thức này ghi một byte (không phải là int) vào luồng đầu ra. Giá trị đã truyền được truyền thành một byte và ba byte đầu tiên của int bị loại bỏ.

write(byte[] buffer)phương pháp

Ghi mảng byte đã cho vào luồng đầu ra. Đó là nó.

write(byte[] buffer, int offset, int length)phương pháp

Ghi một phần của mảng byte đã truyền vào luồng đầu ra. Biến offset cho biết chỉ số của phần tử đầu tiên của mảng và lengthlà độ dài của tập hợp con được viết.

flush()phương pháp

Phương pháp này flush()được sử dụng để buộc bất kỳ dữ liệu nào có khả năng được lưu vào bộ đệm trong luồng hiện tại được ghi vào luồng đích. Điều này có liên quan khi sử dụng bộ đệm và/hoặc nhiều đối tượng luồng được sắp xếp theo chuỗi.

close()phương pháp

Ghi bất kỳ dữ liệu chưa được ghi vào đối tượng mục tiêu. Phương thức này close()không cần được gọi nếu bạn sử dụng một try-with-resourceskhối.

Ví dụ sao chép một tập tin

Mã số Ghi chú
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileInputStream input = new FileInputStream(src);
FileOutputStream output = new FileOutputStream(dest))
{
   byte[] buffer = new byte[65536]; // 64Kb
   while (input.available() > 0)
   {
      int real = input.read(buffer);
      output.write(buffer, 0, real);
   }
}



InputStreamđể đọc từ một tệp
OutputStreamđể ghi vào một tệp Bộ

đệm mà chúng ta sẽ đọc dữ liệu
miễn là có dữ liệu trong luồng

Đọc dữ liệu vào bộ đệm
Ghi dữ liệu từ bộ đệm vào luồng thứ hai

2. Writerlớp học

Lớp Writerhoàn toàn giống với OutputStreamlớp, nhưng chỉ có một điểm khác biệt một lần nữa: nó hoạt động với các ký tự ( char) thay vì byte.

Đây là một lớp trừu tượng: bạn không thể tạo các đối tượng của Writerlớp. Mục tiêu chính của nó là trở thành một lớp cha chung cho hàng trăm lớp con và cung cấp cho chúng các phương thức chung để làm việc với các luồng ký tự.

Các phương thức của Writerlớp (và tất cả các lớp con của nó):

phương pháp Sự miêu tả
void write(int b)
Ghi một ký tự (không phải ký tự int) vào luồng.
void write(char[] buffer)
Ghi một mảng ký tự vào luồng
void write(char[] buffer, off, len)
Ghi một phần của một mảng ký tự vào luồng
void write(String str)
Ghi một chuỗi vào luồng
void write(String str, off, len)
Ghi một phần của chuỗi vào luồng
void flush()
Ghi tất cả dữ liệu được lưu trữ trong bộ đệm vào luồng
void close()
Đóng luồng

Các phương thức này rất giống với các phương thức của OutputStreamlớp, nhưng chúng hoạt động với các ký tự thay vì byte.

Mô tả các phương pháp:

write(int b)phương pháp

Phương thức này ghi một ký tự đơn ( char— không phải ký tự int) vào luồng đầu ra. Giá trị đã truyền được chuyển thành a charvà hai byte đầu tiên bị loại bỏ.

write(char[] buffer)phương pháp

Ghi mảng ký tự đã cho vào luồng đầu ra.

write(char[] buffer, int offset, int length)phương pháp

Ghi một phần của mảng ký tự đã truyền vào luồng đầu ra. Biến offsetcho biết chỉ số của phần tử đầu tiên của mảng, và lengthlà độ dài của tập hợp con được viết.

write(String str)phương pháp

Ghi chuỗi đã cho vào luồng đầu ra.

write(String str, int offset, int length)phương pháp

Ghi một phần của chuỗi đã cho vào luồng đầu ra: chuỗi được chuyển đổi thành một mảng ký tự. Biến offsetcho biết chỉ số của phần tử đầu tiên của mảng, và lengthlà độ dài của tập hợp con được viết.

flush()phương pháp

Phương pháp này flush()được sử dụng để buộc bất kỳ dữ liệu nào có khả năng được lưu vào bộ đệm trong luồng hiện tại được ghi vào luồng đích. Điều này có liên quan khi sử dụng bộ đệm và/hoặc nhiều đối tượng luồng được sắp xếp theo chuỗi.

close()phương pháp

Ghi bất kỳ dữ liệu chưa được ghi vào đối tượng mục tiêu. Phương thức này close()không cần được gọi nếu bạn sử dụng một try-with-resourceskhối.

Ví dụ về chương trình sao chép tệp văn bản:

Mã số Ghi chú
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileReader reader = new FileReader(src);
FileWriter writer = new FileWriter(dest))
{
   char[] buffer = new char[65536]; // 128Kb
   while (reader.ready())
   {
      int real = reader.read(buffer);
      writer.write(buffer, 0, real);
   }
}



Readerđể đọc từ tệp
Writerđể ghi vào tệp Bộ

đệm mà chúng ta sẽ đọc dữ liệu
miễn là có dữ liệu trong luồng

Đọc dữ liệu vào bộ đệm
Ghi dữ liệu từ bộ đệm vào luồng thứ hai

StringWriterlớp học

Có một lớp thú vị khác kế thừa Writerlớp đó: nó được gọi là StringWriter. Nó chứa một chuỗi có thể thay đổi - một StringBufferđối tượng. Và mỗi khi bạn "viết" một cái gì đó cho StringWriterđối tượng, văn bản sẽ được thêm vào bộ đệm bên trong của nó.

Ví dụ:

Mã số Ghi chú
StringWriter writer = new StringWriter();
writer.write("Hello");
writer.write(String.valueOf(123));

String result = writer.toString();
Một luồng ký tự đích ( StringWriter) được tạo
Một chuỗi được ghi vào bộ đệm bên trong StringWriter
Một chuỗi được ghi vào bộ đệm bên trong StringWriter

Chuyển đổi nội dung của một đối tượng thành một chuỗi

Trong trường hợp này, StringWriterlớp về cơ bản là một trình bao bọc bên trên StringBufferlớp, nhưng StringWriterlớp này là hậu duệ của Writerlớp luồng và nó có thể được sử dụng trong chuỗi các đối tượng luồng. Đây là một tính chất khá hữu ích trong thực tế.



3. PrintStreamlớp học

Các lớp luồng đầu ra cũng có thể được đưa vào một chuỗi với các luồng trung gian ghi dữ liệu vào luồng đích được truyền cho chúng. Chế độ xem chung về sự tương tác của các luồng này trông như thế này:

lớp PrintStream

Điều thú vị và linh hoạt nhất trong tất cả các luồng đầu ra trung gian là PrintStream. Nó có hàng chục phương thức và có tới 12 hàm tạo.

Lớp PrintStreamkế thừa FilterOutputStreamlớp, lớp kế thừa OutputStream. Điều đó có nghĩa là PrintStreamlớp này có tất cả các phương thức của các lớp cha bên cạnh các phương thức riêng của nó . Dưới đây là những điều thú vị nhất:

phương pháp Sự miêu tả
void print(obj)
Chuyển đổi đối tượng đã truyền thành một chuỗi và xuất nó sang luồng đích.
void println(obj)
Chuyển đổi đối tượng đã truyền thành một chuỗi và xuất nó sang luồng đích. Thêm ngắt dòng ở cuối
void println()
Xuất ký tự ngắt dòng tới luồng mục tiêu
PrintStream format(String format, args...)
Xây dựng và xuất ra một chuỗi dựa trên chuỗi định dạng và các đối số đã truyền; tương tự như String.format()phương pháp

Và hàng chục phương pháp này ở đâu, bạn hỏi?

Chà, nó có nhiều biến thể của phương thức print()println()với các tham số khác nhau. Chúng có thể được tóm tắt trong bảng này.

Chúng tôi sẽ không đi sâu vào các phương pháp này, vì bạn đã biết rõ về chúng. Bạn có thể đoán những gì tôi đang nhận được ở?

Nhớ không System.out.println()? Nhưng nó có thể được viết trong hai dòng:

Mã số Đầu ra bảng điều khiển
PrintStream stream = System.out;
stream.println("Hello!");
Hello!

Lệnh yêu thích của chúng tôi là gọi phương thức trên biến tĩnh của lớp. Và kiểu của biến này là .System.out.println()println()outSystemPrintStream

Trong nhiều cấp độ CodeGym và trong hầu hết mọi tác vụ, bạn đã gọi các phương thức của PrintStreamlớp mà không hề hay biết!

Công dụng thực tế

Java có lớp thú vị này được gọi là ByteArrayOutputStream, là một mảng byte phát triển động kế thừa OutputStream.

Một ByteArrayOutputStreamđối tượng và PrintStreamđối tượng có thể được xâu chuỗi như thế này:

Mã số Sự miêu tả
ByteArrayOutputStream baos = new ByteArrayOutputStream();

try(PrintStream stream = new PrintStream(baos))
{
   stream.println("Hello");
   stream.println(123);
}

String result = baos.toString();

System.out.println(result);
Tạo bộ đệm ghi trong bộ nhớ

Bọc bộ đệm trong một PrintStreamđối tượng

Ghi dữ liệu vào bàn điều khiển



Chuyển mảng thành chuỗi!

Đầu ra bảng điều khiển:
Hello!
123