Chính xác thì “Stream” và “Buffer” có nghĩa là gì trong Java I / O?


82

Tôi vừa học về cách sử dụng đầu vào / đầu ra BufferedReader.

Tôi muốn biết chính xác ý nghĩa của thuật ngữ StreamBuffer?

Ngoài ra, dòng mã này phục vụ chúng ta những gì:

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

Câu trả lời:


201

Java có hai loại lớp cho đầu vào và đầu ra (I / O): luồng và trình đọc / ghi .

Suối ( InputStream, OutputStreamvà tất cả mọi thứ mà kéo dài này) là để đọc và ghi dữ liệu nhị phân từ các tập tin, mạng, hoặc bất cứ thiết bị nào khác.

Người đọc và người viết là để đọc và viết văn bản (ký tự). Chúng là một lớp trên đầu các luồng, chuyển đổi dữ liệu nhị phân (byte) thành ký tự và ngược lại, sử dụng mã hóa ký tự .

Việc đọc dữ liệu từ từng byte trên đĩa rất kém hiệu quả. Một cách để tăng tốc là sử dụng bộ đệm: thay vì đọc từng byte một, bạn đọc vài nghìn byte cùng một lúc và đặt chúng vào bộ đệm, trong bộ nhớ. Sau đó, bạn có thể xem từng byte trong bộ đệm một.

Hướng dẫn Java của Oracle về I / O giải thích nó một cách chi tiết.

Nhìn vào dòng mã bạn đã cung cấp:

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

System.inlà một InputStream. Bạn tạo một tài InputStreamReaderkhoản đọc các byte từ đó System.in. Sau đó, bạn bọc nó trong một BufferedReader.

Vì vậy, cuối cùng, bạn có một BufferedReaderđọc từ một InputStreamReaderđọc từ System.in.


1
Cảm ơn bạn đã trả lời nhưng tôi có một sự nhầm lẫn, như bạn đã nói chúng tôi đọc vài nghìn byte cùng một lúc và đặt chúng vào bộ đệm; vậy điều này có nghĩa là bộ đệm chỉ là một nơi trong bộ nhớ nơi chúng ta lưu trữ mọi thứ?
user122345656

3
@Jesper. Bạn đã nói "Một cách để tăng tốc độ là sử dụng bộ đệm: thay vì đọc từng byte một, bạn đọc vài nghìn byte cùng một lúc và đặt chúng vào bộ đệm, trong bộ nhớ. Sau đó, bạn có thể xem các byte trong bộ đệm từng cái một. " Đúng, nó đúng nhưng tôi nghĩ với bộ đệm cũng vậy, byte đơn được đọc tại một thời điểm. Sự khác biệt duy nhất tôi nghĩ rằng nó được đặt trong bộ đệm và chương trình sau đó đọc nó từ bộ đệm thay vì đĩa
M Sach

7
@ user122345656 Đúng, bộ đệm là một nơi trong bộ nhớ để tạm thời lưu trữ dữ liệu.
Jesper

14
@MSach Hãy nghĩ đến điều gì sẽ xảy ra khi bạn muốn đọc dữ liệu từ đĩa cứng. Để đọc một byte tại một vị trí nhất định, bạn phải đợi cho đến khi đĩa quay cho đến khi phần đầu nằm phía trên vị trí trên đĩa nơi có byte cần đọc. Nếu bạn chỉ đọc 1 byte tại thời điểm đó và byte tiếp theo sau đó, bạn phải đợi cho đến khi đĩa quay hoàn toàn để đọc byte tiếp theo. Sẽ hiệu quả hơn nhiều khi đọc một khối byte liên tiếp.
Jesper

2
@parsecer Luồng là để đọc các byte; độc giả là để đọc văn bản (ký tự). InputStreamReaderlà một trình bao bọc xung quanh một InputStreamcho phép bạn đọc văn bản từ một InputStream. Nếu bạn chỉ muốn đọc byte (không phải ký tự), bạn không cần InputStreamReader. Nó hữu ích nếu bạn muốn diễn giải các byte dưới dạng ký tự văn bản.
Jesper

19

Đệm:

Nó là một vùng của bộ nhớ vật lý được sử dụng để lưu trữ tạm thời dữ liệu trong khi nó đang được di chuyển từ nơi này sang nơi khác. Đó là bộ nhớ lưu trữ vật lý sẽ là RAM (ram) trong hầu hết các trường hợp.

Nhưng từ ngữ cảnh của câu hỏi này, Buffer được sử dụng trong khi đọc / ghi dữ liệu. Nó không cần được sử dụng trong khi di chuyển dữ liệu từ nơi này sang nơi khác.

Ví dụ cho bộ đệm: Nếu hệ thống của bạn có 4 GB RAM, 4 KB bộ nhớ (RAM) có thể được hệ thống cấp phát cho Bộ đệm . KB - Kilobyte (s), GB - Gigabyte (s)

Luồng I / O (hoặc) Luồng:

I / O Stream đại diện cho một nguồn đầu vào hoặc một điểm đến đầu ra. Một luồng có thể đại diện cho nhiều loại nguồn và đích khác nhau, bao gồm tệp đĩa, thiết bị, chương trình khác và mảng bộ nhớ.

I / O có nghĩa là Đầu vào / Đầu ra.

Vì vậy, Input Stream có thể là một nguồn đầu vào như tệp đĩa, kết nối mạng, v.v.

Và, Dòng đầu ra có thể là đích đầu ra như tệp đĩa, kết nối mạng, v.v.

Theo tài liệu chính thức của JAVA , Luồng có 3 loại.

  1. Luồng Byte (đọc hoặc ghi byte)
  2. Dòng ký tự (đọc hoặc ghi ký tự)
  3. Luồng được đệm (đọc từ hoặc ghi vào Bộ đệm để đạt hiệu quả)

Luồng Byte:

Chúng thực hiện đầu vào và đầu ra của byte 8-bit. Tất cả các lớp luồng byte được giảm xuống từ InputStreamOutputStream .

Các lớp Byte Input Stream nhận đầu vào dưới dạng byte thô . Các lớp Luồng đầu ra Byte cho đầu ra dưới dạng các byte thô .

InputStream- Các lớp con đã biết trực tiếp

AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream.

OutputStream- Các lớp con đã biết trực tiếp

ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream

Luồng ký tự: Chúng là một lớp nằm trên Luồng Byte. Chúng chuyển đổi byte (dữ liệu nhị phân) thành ký tự và ký tự thành byte, sử dụng mã hóa ký tự.

Tất cả các lớp dòng ký tự đều có nguồn gốc từ ReaderWriter .

Reader - Các lớp con đã biết trực tiếp

BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader

Writer - Các lớp con đã biết trực tiếp

BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter

Luồng Byte & Luồng ký tự sử dụng I / O không có bộ đệm .

Điều này có nghĩa là mỗi yêu cầu đọc hoặc ghi được xử lý trực tiếp bởi hệ điều hành bên dưới. Điều này có thể làm cho một chương trình kém hiệu quả hơn nhiều, vì mỗi yêu cầu như vậy thường kích hoạt truy cập đĩa, hoạt động mạng hoặc một số hoạt động khác tương đối tốn kém. Để giảm bớt loại chi phí này, nền tảng Java triển khai các luồng I / O được đệm.

Luồng được đệm:

Các luồng đầu vào có bộ đệm đọc dữ liệu từ một vùng nhớ được gọi là bộ đệm ; API đầu vào gốc chỉ được gọi khi bộ đệm trống.

Tương tự, các luồng đầu ra có bộ đệm ghi dữ liệu vào bộ đệm và API đầu ra gốc chỉ được gọi khi bộ đệm đầy.

Một chương trình có thể chuyển đổi một bộ đệm dòng thành một đệm dòng bằng cách sử dụng gói thành ngữ, nơi mà không có bộ đệm dòng đối tượng sẽ được chuyển cho các nhà xây dựng cho một đệm lớp suối.

Thí dụ:

inputStream = new BufferedReader(new FileReader("xanadu.txt"));
outputStream = new BufferedWriter(new FileWriter("characteroutput.txt"));

Có 4 lớp luồng được đệm được sử dụng để bọc các luồng không được đệm:

Để tạo Byte Stream được đệm , sử dụng và các lớp.BufferedInputStreamBufferedOutputStream

Để tạo Dòng ký tự đệm , sử dụng và các lớp.BufferedReaderBufferedWriter


1
Tôi đang tìm kiếm lời giải thích chuyên sâu như vậy cho java io. Cảm ơn rât nhiều.
Arif Reza

14

Đó là một câu hỏi trong tâm trí của những ai bắt đầu làm việc trên gói java.io. Để trả lời các thuật ngữ câu hỏi của bạn, InputStreamReader và BufferedReader chỉ đại diện cho các đối tượng java (không có gì đặc biệt về chúng) nhưng chúng được tạo cho các hoạt động io như đọc và ghi từ / đến các đầu vào / đầu ra khác nhau như tệp, đối tượng, v.v.

Bây giờ chúng ta hãy đến hàng

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

InputStreamReader là lớp để đọc dòng đầu vào của các byte, nhưng để đọc từng byte là một thao tác tốn kém, vì vậy chúng tôi đang quấn nó xung quanh BufferedReader để có bộ đệm (đó là mẫu trang trí)

Vì vậy, những gì sẽ xảy ra là ngay cả trước khi bạn bắt đầu đọc, bufferedReader sẽ lưu trữ một số đoạn byte trong thanh ghi và khi bạn thực hiện thao tác đọc. nó sẽ được đọc từ vị trí đó ít tốn kém hơn nhiều so với đọc từ bảng điều khiển / tệp Nhưng trong trường hợp của InputStreamReader, khi bạn thực hiện thao tác đọc mỗi khi thao tác truy cập đĩa diễn ra


1 nhưng tôi muốn IF sẽ có thêm các liên kết tham chiếu cho các trang trí thông tin và từng hoạt động thời gian truy cập đĩa diễn ra sentances
Shareef

Đoạn cuối cùng đó tổng hợp những lợi ích tốt. Cảm ơn vì điều đó.
Dave Voyles

3

Luồng là kết nối và thông tin thực tế được chuyển giữa các điểm. Bộ đệm là một bộ chứa lưu trữ lưu trữ một phần hoặc tất cả dữ liệu được truyền trực tuyến và cấp dữ liệu này đến thiết bị đầu ra.

Tất nhiên, vấn đề là nếu luồng chậm quá tốc độ dữ liệu cần thiết để hiển thị dữ liệu, thì đầu ra sẽ tạm dừng. Bộ đệm ngăn chặn điều này.


Cảm ơn bạn đã trả lời. Nhưng một câu hỏi nảy ra trong đầu tôi là ý bạn muốn nói về dữ liệu được truyền trực tuyến là gì?
user122345656 14/04

1
Xin lỗi vì hồi âm muộn. Nếu bạn hình dung ví dụ đơn giản về Tệp 10Mb trên Máy chủ. Máy chủ có toàn bộ tệp, nhưng nó không thể gửi toàn bộ tệp trong một Gói. Thay vào đó, tệp được chia thành một số khối hữu hạn. Mỗi khối sau đó được gửi đến máy tính từ xa và được tập hợp lại. Đối với truyền dữ liệu trực tiếp, lý thuyết tương tự cũng được áp dụng. Nhưng máy chủ lấy dữ liệu trực tiếp và gửi nó dưới dạng một streamgói tin. Sau đó, Máy tính từ xa lưu trữ từng Gói trong Bộ đệm. Máy tính từ xa đọc dữ liệu từ bộ đệm của nó và tạo video nói từ điều này. Tôi hi vọng cái này giúp được!
PGallagher

1

Bộ đệm là một phần trong bộ nhớ được sử dụng để lưu trữ luồng dữ liệu từ các thiết bị ngoại vi. Sau đó từ vùng đệm này luồng dữ liệu này được thu thập và lưu trữ trong các biến. Luồng có thể được định nghĩa là một luồng dữ liệu liên tục.

Thuật ngữ “đầu vào / đầu ra” không có nghĩa gì khác hơn là di chuyển dữ liệu vào và ra khỏi bộ đệm. Chỉ cần ghi nhớ điều này trong tâm trí của bạn mọi lúc. Các quy trình thực hiện I / O bằng cách yêu cầu hệ điều hành lấy dữ liệu ra khỏi bộ đệm (thao tác ghi) hoặc bộ đệm được lấp đầy bằng dữ liệu (thao tác đọc).
Sơ đồ logic về cách dữ liệu di chuyển

Nói một cách dễ hiểu, hãy tưởng tượng khi bạn nhập dữ liệu vào bàn phím, dữ liệu sẽ di chuyển qua một đường ống ( luồng ) đến bộ đệm và sau đó từ bộ đệm đến đĩa (thao tác ghi). Tương tự khi dữ liệu di chuyển từ đĩa sang bộ đệm và từ bộ đệm sang bảng điều khiển của bạn thì đó là hoạt động đọc.

Bạn có thể đọc các liên kết để hiểu rõ hơn. Hy vọng nó giúp!.
Bộ đệm trong Java là gì,
hãy nhập mô tả liên kết vào đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.