Java I / O'da "Akış" ve "Buffer" tam olarak ne anlama geliyor?


85

Sadece girdi / çıktı kullanmayı öğrendim BufferedReader.

Ben tam olarak terimin anlamları ne olduğunu bilmek istediğini Streamve Buffer?

Ayrıca bu kod satırı bize ne sağlar:

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

Yanıtlar:


202

Java'nın giriş ve çıkış (G / Ç) için iki tür sınıfı vardır: akışlar ve okuyucular / yazarlar .

Akışları ( InputStream, OutputStreamve bunlar uzanan her şey) okuma ve dosyalara, ağ, ya da her türlü diğer cihazdan ikili veri yazma içindir.

Okuyucular ve yazarlar metin (karakterler) okumak ve yazmak içindir. Bir karakter kodlaması kullanarak ikili verileri (baytları) karakterlere ve geri dönüştüren akışların üstünde bir katmandır .

Disk bayt bayt'tan veri okumak çok verimsizdir. Hızlandırmanın bir yolu arabellek kullanmaktır: her seferinde bir bayt okumak yerine, bir kerede birkaç bin baytı okur ve bunları bir arabelleğe, belleğe koyarsınız. Daha sonra arabellekteki baytlara tek tek bakabilirsiniz.

Oracle'ın I / O hakkındaki Java öğreticisi bunu ayrıntılı olarak açıklamaktadır.

Sağladığınız kod satırına bakın:

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

System.inbir InputStream. Bir yaratmak InputStreamReadergelen bayt okur hangi System.in. Sonra bunu bir BufferedReader.

Sonunda, BufferedReaderokuyan bir InputStreamReaderşeyden okuyan bir o var System.in.


1
Cevabınız için teşekkür ederim ama kafam karışık. Dediğin gibi, bir seferde birkaç bin baytı okuyup ara belleğe koyduk; yani bu, ara belleğin sadece bir şeyleri depoladığımız bellekte bir yer olduğu anlamına mı geliyor?
user122345656

3
@Jesper. "Hızlandırmanın bir yolu arabellek kullanmaktır: her seferinde bir bayt okumak yerine, bir kerede birkaç bin bayt okur ve bunları bir arabelleğe, belleğe koyarsınız. Sonra baytlara bakabilirsiniz. tamponda tek tek. " Evet doğru ama bence tamponla da bir seferde tek bayt okunur. Tek fark tampona konulduğunu ve programın ardından disk yerine arabellekten okuduğunu düşünüyorum
M Sach

7
@ user122345656 Evet, arabellek, verileri geçici olarak depolamak için bellekte bir yerdir.
Jesper

14
@MSach Bir sabit diskten veri okumak istediğinizde ne olacağını bir düşünün. Belirli bir konumdaki bir baytı okumak için, kafa diskteki okunacak baytın bulunduğu konumun üzerine gelene kadar diskin dönmesini beklemeniz gerekir. O anda sadece 1 bayt okursanız ve sonraki baytı daha sonra okursanız, disk bir sonraki baytı okumak için tam bir dönüş yapana kadar beklemeniz gerekir. Bir ardışık bayt bloğunu okumak çok daha etkilidir.
Jesper

2
@parsecer Akışları bayt okumak içindir; okuyucular metin (karakter) okumak içindir. InputStreamReaderBir etrafında sarıcı InputStreambir metni okumanızı sağlar InputStream. Eğer sadece bayt okumak istiyorsanız (karakterleri değil), ihtiyacınız yok InputStreamReader. Baytları metin karakterleri olarak yorumlamak istiyorsanız kullanışlıdır.
Jesper

20

Tampon:

Bu bir olan bölge fiziksel bellek depolama başka bir yerden bir yere taşınırken verileri geçici olarak saklamak için kullanılan. Yani fiziksel bellek depolama olacağını RAM çoğu durumda (Rasgele erişim belleği).

Ancak bu sorunun bağlamında, Buffer veri okurken / yazarken kullanılır. Verileri bir yerden diğerine taşırken kullanılmasına gerek yoktur.

Arabellek için örnek: Sisteminizde 4 GB RAM varsa, sistem tarafından Arabellek için 4 KB bellek (RAM) ayrılabilir . KB - Kilobayt (lar), GB - Gigabayt (lar)

G / Ç Akışı (veya) Akışı:

G / Ç Akışı , bir giriş kaynağını veya bir çıkış hedefini temsil eder. Akış, disk dosyaları, aygıtlar, diğer programlar ve bellek dizileri dahil olmak üzere birçok farklı türde kaynağı ve hedefi temsil edebilir.

G / Ç, Giriş / Çıkış anlamına gelir.

Dolayısıyla, Giriş Akışı disk dosyası, ağ bağlantısı vb. Gibi bir giriş kaynağı olabilir.

Ve Çıktı Akışı, disk dosyası, ağ bağlantısı vb. Gibi bir çıktı hedefi olabilir.

Göre JAVA resmi belgeler , Akışları 3 türlüdür.

  1. Bayt Akışları ( Baytları okuyun veya yazın)
  2. Karakter Akışları ( Karakterleri okuyun veya yazın)
  3. Arabelleğe Alınmış Akışlar ( verimlilik için Arabellekten okuyun veya Arabelleğe yazın)

Bayt Akışları:

8 bitlik bayt giriş ve çıkışını gerçekleştirirler. Tüm bayt akışı sınıfları, InputStream ve OutputStream'den türemiştir .

Bayt Girdi Akışı sınıfları girdileri ham bayt olarak alır . Bayt Çıktı Akışı sınıfları, çıktıları ham bayt olarak verir .

InputStream- Doğrudan Bilinen Alt Sınıflar

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

OutputStream- Doğrudan Bilinen Alt Sınıflar

ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream

Karakter Akışları: Bayt Akışlarının üstündeki katmandır. Karakter kodlaması kullanarak baytları (ikili veriler) karakterlere ve karakterleri bayta dönüştürürler.

Tüm karakter akışı sınıfları Reader ve Writer'dan türemiştir .

Reader - Doğrudan Bilinen Alt Sınıflar

BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader

Writer - Doğrudan Bilinen Alt Sınıflar

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

Bayt Yayınları ve Karakter Akışları kullanmak tamponsuz I / O'yu .

Bu, her okuma veya yazma talebinin doğrudan temeldeki işletim sistemi tarafından işlendiği anlamına gelir. Bu, bir programı çok daha az verimli hale getirebilir, çünkü bu tür isteklerin her biri genellikle disk erişimini, ağ etkinliğini veya nispeten pahalı olan diğer bazı işlemleri tetikler. Bu tür ek yükü azaltmak için, Java platformu arabelleğe alınmış G / Ç akışları uygular.

Arabelleğe Alınmış Akışlar:

Tamponlanmış giriş akışları , tampon olarak bilinen bir hafıza alanından verileri okur ; yerel girdi API'si yalnızca arabellek boş olduğunda çağrılır.

Benzer şekilde, arabelleğe alınmış çıktı akışları verileri bir arabelleğe yazar ve yerel çıktı API'si yalnızca arabellek dolu olduğunda çağrılır.

Bir program, arabelleğe alınmamış bir akışı , arabelleğe alınmamış akış nesnesinin bir arabelleğe alınmış akış sınıfı için yapıcıya iletildiği sarma deyimini kullanarak arabelleğe alınmış bir akışa dönüştürebilir .

Misal:

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

Arabelleğe alınmamış akışları sarmalamak için kullanılan 4 arabelleğe alınmış akış sınıfı vardır:

Arabelleğe alınmış Bayt Akışları oluşturmak için, BufferedInputStreamve BufferedOutputStreamsınıflarını kullanın .

Arabelleğe alınmış Karakter Akışları oluşturmak için, BufferedReaderve BufferedWritersınıflarını kullanın .


1
Java io için böylesine derinlemesine bir açıklama arıyordum. Çok teşekkür ederim.
Arif Reza

14

Peki bu, java.io paketi üzerinde çalışmaya başlayan herkesin aklında bir soru. Soru terimlerinize cevap vermek için, InputStreamReader ve BufferedReader yalnızca java nesnelerini temsil eder (onlar hakkında özel bir şey yoktur), ancak dosya, nesne vb.

Şimdi satıra gelelim

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

InputStreamReader, baytların giriş akışını okuyan sınıftır, ancak her bir baytı okumak pahalı bir işlemdir, bu yüzden onu arabelleğe almak için BufferedReader'ın etrafına sarıyoruz (ki bu da dekoratör modelidir)

Öyleyse, siz okumaya başlamadan önce bile olacak, bufferedReader kayıtta ve siz okuma işlemini gerçekleştirdiğinizde bazı bayt yığınlarını saklayacaktır. Bu, konsoldan / dosyadan okumaktan çok daha ucuz olan bu konumdan okunacaktır.Ancak InputStreamReader durumunda, disk erişim işlemi her gerçekleştiğinde okuma işlemini gerçekleştirdiğinizde


+1, ancak bilgi dekoratörü için bağlantı referansı eklemeyi ve disk erişim işlemi her cümle gerçekleştiğinde tercih ederim
shareef

Bu son paragraf faydaları iyi özetliyor. Bunun için teşekkür ederim.
Dave Voyles

3

Akış, noktalar arasında aktarılan bağlantı ve gerçek bilgidir. Tampon, akıtılan verilerin bir kısmını veya tamamını depolayan ve bunu çıktı cihazına besleyen bir saklama kabıdır.

Tabii ki, nokta, akış verileri göstermek için gereken veri hızının ötesinde yavaşlarsa, çıktının duraklayacağıdır. Tampon bunu engeller.


Cevap için teşekkürler Ama aklıma gelen bir soru, akan verilerle ne demek istiyorsun?
user122345656

1
Geç cevap verdiğim için özür dilerim. Sunucudaki 10Mb Dosyanın basit bir örneğini hayal ederseniz. Sunucuda tam dosya vardır, ancak tüm dosyayı tek bir Paket içinde gönderemez. Bunun yerine, dosya sınırlı sayıda bloğa bölünür. Her blok daha sonra uzak bilgisayara gönderilir ve yeniden birleştirilir. Canlı veri akışı için aynı teori geçerlidir. Ancak sunucu canlı verileri alır ve bunları streampaketler halinde gönderir . Uzak Bilgisayar daha sonra her Paketi bir Tamponda depolar. Uzak Bilgisayar, verileri arabelleğinden okur ve bundan bir video oluşturur. Umarım bu yardımcı olur!
PGallagher

1

Bir Tampon bellek, çevresel cihazlardan veri akışını depolamak için kullanılan bir kısımdır. Daha sonra bu tampondan bu veri akışı toplanır ve değişkenler halinde saklanır. Bir akış, sürekli bir veri akışı olarak tanımlanabilir.

"Giriş / çıkış" terimi, verileri arabelleklerin içine ve dışına taşımaktan başka bir şey ifade etmez. Bunu her zaman aklınızda tutun. İşlemler, işletim sisteminden verilerin bir arabellekten boşaltılmasını (yazma işlemi) veya bir arabelleğin verilerle doldurulmasını (okuma işlemi) talep ederek G / Ç gerçekleştirir.
Verilerin nasıl hareket ettiğini gösteren Mantıksal Diyagram

Basit bir ifadeyle, bir klavyede veri yazdığınızda, verilerin bir kanaldan ( akış ) arabelleğe ve ardından arabellekten diske (yazma işlemi) geçtiğini hayal edin . Benzer şekilde, veriler diskten arabelleğe ve arabellekten konsolunuza taşındığında , okuma işlemi olur.

Daha iyi anlamak için bağlantıları okuyabilirsiniz. Umarım yardımcı olur!.
Java'da arabellek nedir
buraya bağlantı açıklamasını girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.