Akarsu kavramını açıklayabilir misiniz?


186

Bir akışın bir bayt dizisinin temsili olduğunu anlıyorum. Her akış, verilen destek deposuna bayt okumak ve yazmak için araçlar sağlar. Ama akışın anlamı nedir? Destek mağazası neden etkileşimde bulunduğumuz şey değil?

Her ne sebeple olursa olsun, bu kavram benim için tıklamıyor. Bir sürü makale okudum, ama sanırım bir benzetmeye ihtiyacım var.

Yanıtlar:


234

"Akış" kelimesi seçilmiştir çünkü (gerçek hayatta) onu kullandığımızda iletmek istediğimiz şeye çok benzer bir anlam ifade eder.

Bir süre için destek mağazasını unutalım ve bir su akışının benzetmesini düşünmeye başlayalım. Bir nehirde su sürekli aktığı gibi sürekli bir veri akışı alırsınız. Verilerin nereden geldiğini bilmeniz gerekmez ve çoğu zaman buna gerek yoktur; bir dosyadan, soketten veya başka bir kaynaktan olsun, gerçekten önemli değil (olmamalı). Bu, bir su akışı almaya çok benzer, böylece nereden geldiğini bilmenize gerek yoktur; bir gölden, bir çeşmeden veya başka bir kaynaktan olsun, gerçekten önemli değil (olmamalı).

Bununla birlikte, nereden geldiğine bakılmaksızın, yalnızca ihtiyacınız olan verileri almayı önemsediğinizi düşünmeye başladığınızda, diğer insanların bahsettiği soyutlamalar daha net hale gelir. Akarsu satabileceğinizi düşünmeye başlarsınız ve yöntemleriniz yine de mükemmel çalışır. Örneğin, bunu yapabilirsiniz:

int ReadInt(StreamReader reader) { return Int32.Parse(reader.ReadLine()); }

// in another method:
Stream fileStream = new FileStream("My Data.dat");
Stream zipStream = new ZipDecompressorStream(fileStream);
Stream decryptedStream = new DecryptionStream(zipStream);
StreamReader reader = new StreamReader(decryptedStream);

int x = ReadInt(reader);

Gördüğünüz gibi, işlem mantığınızı değiştirmeden giriş kaynağınızı değiştirmek çok kolay hale gelir. Örneğin, verilerinizi dosya yerine bir ağ soketinden okumak için:

Stream stream = new NetworkStream(mySocket);
StreamReader reader = new StreamReader(stream);
int x = ReadInt(reader);

Olabildiğince kolay. Ve bunun için bir akış "sarıcı" oluşturabildiğiniz sürece, herhangi bir giriş kaynağını kullanabileceğiniz gibi güzellik devam ediyor. Bunu bile yapabilirsiniz:

public class RandomNumbersStreamReader : StreamReader {
    private Random random = new Random();

    public String ReadLine() { return random.Next().ToString(); }
}

// and to call it:
int x = ReadInt(new RandomNumbersStreamReader());

Görmek? Metodunuz giriş kaynağının ne olduğu umurumda olmadığı sürece, kaynağınızı çeşitli şekillerde özelleştirebilirsiniz. Soyutlama, mantığı işlemden gelen girdiyi çok zarif bir şekilde ayırmanızı sağlar.

Kendimizi yarattığımız akışın bir destek mağazası olmadığını, ancak yine de amaçlarımıza mükemmel bir şekilde hizmet ettiğini unutmayın.

Özetlemek gerekirse, bir akış başka bir kaynağı gizleyerek (soyutlayarak) yalnızca bir girdi kaynağıdır. Soyutlamayı bozmadığınız sürece, kodunuz çok esnek olacaktır.


6
Soyut düşünme (ve açıklama) kanınızda gibi görünüyor;) Suya benzetmeniz (ve böylece mecazi referanslar) bana Ömer Hayyam'ı hatırlattı.
java.is.for.desktop

@HosamAly Açıklamanız çok açık, ancak bir şey beni örnek kodda biraz karıştırıyor. Dize int için açık dönüşüm otomatik olarak ReadInt yapıyor? Ben de ReadString yapabileceğime inanıyorum?
Rushino

1
@Rushino Yukarıdaki kodda hiç dönüşüm yok. Yöntem ReadInt, en üstte tanımlanır ve int.Parsedöndürülen dizeyi alan reader.ReadLine()ve ayrıştıran dizeyi alır . Tabii ki benzer bir ReadStringyöntem yaratabilirsiniz . Bu yeterince açık mı?
Hosam Aly

İyi koy. Benim için akarsu, programlamanın bütününde en basit ve güçlü jenerik soyutlamalar. .Net basic'e sahip olmak Stream.Copybirçok uygulamada hayatı çok kolaylaştırır.
Felype

38

Mesele şu ki, destek mağazasının ne olduğunu bilmek zorunda kalmamalısınız - bu bir soyutlama. Gerçekten de, orada bile olmayabilir olmak yedekleme deposunun - Bir ağdan okuma olabilir ve veri hiç "saklı" asla.

Bir dosya sistemi, bellek, ağ veya akış fikrini destekleyen başka bir şeyle konuştuğunuzda çalışan kod yazabiliyorsanız, kodunuz çok daha esnektir.

Buna ek olarak, akışlar genellikle birlikte zincirlenir - içine konulan her şeyi sıkıştıran, sıkıştırılmış formu başka bir akışa veya verileri şifreleyen bir akışa yazan bir akışınız olabilir. Diğer uçta bunun tersi olur zincir, şifre çözme, açma veya her neyse.


Yukarıdaki @HosamAly örneğinde kullanılan farklı akış okuyucu türleri, destek mağazasının ne olduğunu bildiğiniz anlamına gelmiyor mu? FileStream, NetworkStream vb ... bu tür kaynaklardan okuyorum. Ayrıca, destek deposunun ne olabileceğini bilmediğiniz ve program çalışırken dinamik olarak seçileceği durumlar var mı? Ben şahsen bununla karşılaşmadım ve daha fazlasını bilmek istiyorum.
user137717

Ayrıca, veriler üretilirken bazı veriler yoluyla veri akışı yapabilir veya işleme başladığımda üzerinde çalışmak istediğim tam veri kümesine erişmem gerekiyor mu?
user137717

@ user137717: Hayır, yalnızca StreamReader- veya daha iyisi alırsanız TextReader, kodunuz veri akışının altında ne tür bir akış olduğunu bilmez. Daha doğrusu, BaseStreamtürü bulmak için özelliği kullanabilir - ancak kodunuzun daha önce hiç görmediği bir tür olabilir. Mesele şu ki, umursamamanız gerekir. Ve evet, olabilir kesinlikle bazen bir ağ akışı için kullanılacak ve bazen bir dosya akışı için kullanılacak yazı kodu sonunda. Bir süreç boyunca veri boruları akışlarına gelince - bu süreç içinde yapılmayacaktı ... akış sağlayıcısı olurdu.
Jon Skeet

30

Akışın amacı, sizinle destek deposu arasında bir soyutlama katmanı sağlamaktır. Dolayısıyla, bir akış kullanan belirli bir kod bloğunun, destek deposunun bir disk dosyası, bellek vb.


Evet, kodunuzu kırmadan akış türünü değiştirmenize olanak tanır. Örneğin, bir çağrıdaki bir dosyadan ve sonraki çağrıda bir bellek arabelleği okuyabilirsiniz.
Craig

Bunu yapmak istemenizin nedeninin, genellikle bir dosyayı okurken veya yazarken dosya arama yeteneğine ihtiyacınız olmadığının ve böylece aynı kodun kolayca okunması veya yazılması için kullanılabileceği bir akış kullanıyorsanız örneğin bir ağ soketi.
alxp

11

Bu akarsularla değil, yüzmeyle ilgili. Bir Akışı yüzebiliyorsanız, karşılaştığınız herhangi bir Akışı yüzebilirsiniz.


7

Yankı odasına eklemek için, akış bir soyutlamadır, bu nedenle alttaki mağazayı önemsemezsiniz. Akışlı ve akışsız senaryoları düşündüğünüzde en mantıklıdır.

Dosyalar çoğunlukla ilgisizdir, çünkü akışlar aşina olduğum akış tabanlı olmayan yöntemlerin üstünde ve ötesinde pek bir şey yapmaz. İnternet dosyalarıyla başlayalım.

İnternetten bir dosya indirmek istersem, bir TCP soketi açmam, bağlantı kurmam ve bayt kalmayana kadar bayt almam gerekiyor. Ben bir arabellek yönetmek, beklenen dosyanın boyutunu bilmek ve bağlantı düştü algılamak ve uygun şekilde işlemek için kod yazmak zorunda.

Diyelim ki bir çeşit TcpDataStream nesnesi var. Uygun bağlantı bilgileriyle oluşturuyorum, daha sonra bayt kalmadığını söyleyene kadar akıştaki baytları okuyorum. Akış, arabellek yönetimini, veri sonu koşullarını ve bağlantı yönetimini yönetir.

Bu şekilde akışlar G / Ç'yi kolaylaştırır. Akışın yaptığı şeyi yapan bir TcpFileDownloader sınıfı yazabilirsiniz, ancak daha sonra TCP'ye özgü bir sınıfınız vardır. Çoğu akış arabirimi bir Read () ve Write () yöntemi sağlar ve daha karmaşık kavramlar dahili uygulama tarafından işlenir. Bu nedenle, bellek, disk dosyaları, soketler ve diğer birçok veri deposunu okumak veya bunlara yazmak için aynı temel kodu kullanabilirsiniz.


5

Kullandığım görselleştirme, gerçek fabrikalarda değil, konveyör bantlar çünkü bunun hakkında hiçbir şey bilmiyorum, ancak öğelerin çizgiler boyunca hareket ettiği ve bir dizi aptal cihaz tarafından damgalandığı ve kutlandığı ve sayıldığı ve kontrol edildiği karikatür fabrikalarında.

Bir şeyi yapan basit bileşenleriniz var, örneğin bir pastayı kiraz üzerine koymak için bir cihaz. Bu cihaz, kirazsız keklerden oluşan bir giriş akışına ve kirazlı keklerden oluşan bir çıkış akışına sahiptir. İşleminizi bu şekilde yapılandırmaya değinmenin üç avantajı vardır.

Öncelikle bileşenleri kendileri basitleştirir: bir kekin üzerine çikolata sosu koymak istiyorsanız, kekler hakkında her şeyi bilen karmaşık bir cihaza ihtiyacınız yoktur, içine çikolatalı krema beslenen her şeye yapıştıran aptal bir cihaz oluşturabilirsiniz. karikatürler, bu bir sonraki öğenin kek olmadığını, Wile E. Coyote olduğunu bilmiyor.

İkincisi, cihazları farklı dizilere koyarak farklı ürünler oluşturabilirsiniz: belki keklerinizin buzlanmanın üstünde kiraz yerine kirazın üstünde buzlanma olmasını isteyebilirsiniz ve bunu sadece cihazları hat üzerinde değiştirerek yapabilirsiniz .

Üçüncü olarak, cihazların envanteri, boksu veya kutuyu açmayı yönetmesi gerekmez. Bir şeyleri toplamanın ve paketlemenin en verimli yolu değiştirilebilir: belki bugün keklerinizi 48 kutuya koyuyorsunuz ve kamyon yükü ile gönderiyorsunuz, ancak yarın özel siparişlere yanıt olarak altı kutu göndermek istiyorsunuz. Bu tür bir değişiklik, üretim hattının başında ve sonunda makineleri değiştirerek veya yeniden yapılandırarak gerçekleştirilebilir; hattın ortasındaki kiraz makinesinin aynı anda farklı sayıda öğeyi işlemek için değiştirilmesi gerekmez, her zaman bir seferde bir öğe ile çalışır ve girdisinin veya çıktısının nasıl olduğunu bilmek zorunda değildir. gruplandırılmış.


Açıklama olarak analojiye harika bir örnek.
Richie Thomas

5

İlk kez akış hakkında duyduğumda , bir web kamerasıyla canlı akış bağlamındaydı . Yani, bir ana bilgisayar video içeriği yayınlıyor ve diğer ana bilgisayar video içeriğini alıyor. Peki bu akış mı? Şey ... evet ... ama canlı bir akış somut bir kavram ve bence soru soyut Akış kavramına atıfta bulunuyor. Bkz. Https://en.wikipedia.org/wiki/Live_streaming

Hadi devam edelim.


Video, yayınlanabilen tek kaynak değildir. Ses akışı da yapılabilir. Şimdi medya akışından bahsediyoruz. Bkz. Https://en.wikipedia.org/wiki/Streaming_media . Ses kaynaktan hedefe çeşitli şekillerde iletilebilir. Öyleyse bazı veri dağıtım yöntemlerini birbiriyle karşılaştıralım.

Klasik dosya indirme Klasik dosya indirme gerçek zamanlı olarak gerçekleşmez. Kullanılacak dosyayı almadan önce, indirme işleminin tamamlanmasını beklemeniz gerekir.

Aşamalı indirme Aşamalı indirme parçaları, akışlı ortam dosyasından geçici bir arabelleğe veri indirir. Bu arabellekteki veriler kullanılabilir: arabellekteki ses-video verileri oynatılabilir. Bu nedenle kullanıcılar indirirken akışlı medya dosyasını izleyebilir / dinleyebilir. Hızlı iletme ve geri sarma mümkündür, arabellekle birlikte. Her neyse, aşamalı indirme canlı akış değildir.

Akış Gerçek zamanlı olur ve verileri toplar. Akış, canlı yayınlarda uygulanır. Yayını dinleyen istemciler hızlı ileri veya geri sarma yapamazlar. Video akışlarında, veriler oynatıldıktan sonra atılır.

Bir Akış Sunucusu, istemcisiyle iki yönlü bir bağlantı sağlarken, bir Web Sunucusu bir sunucu yanıtından sonra bağlantıyı kapatır.


Ses ve video, yayınlanabilecek tek şey değildir. PHP kılavuzundaki akış kavramına bir göz atalım.

akış, akış davranışı gösteren bir kaynak nesnedir. Yani, doğrusal bir şekilde okunabilir veya doğrusal bir şekilde yazılabilir ve akış içindeki keyfi bir konuma fseek () olabilir. Bağlantı: https://www.php.net/manual/en/intro.stream.php

PHP'de bir kaynak, dosya, veritabanı bağlantısı gibi harici bir kaynağa referanstır. Başka bir deyişle, bir akış okunabilen veya yazılabilen bir kaynaktır. Yani, eğer fopen()birlikte çalışsaydınız, zaten akışlarla çalışmışsınız demektir.

Akışa maruz kalan bir Metin dosyası örneği:

// Let's say that cheese.txt is a file that contains this content: 
// I like cheese, a lot! My favorite cheese brand is Leerdammer.
$fp = fopen('cheese.txt', 'r');

$str8 = fread($fp, 8); // read first 8 characters from stream. 

fseek($fp, 21); // set position indicator from stream at the 21th position (0 = first position)
$str30 = fread($fp, 30); // read 30 characters from stream

echo $str8; // Output: I like c 
echo $str30; // Output: My favorite cheese brand is L

Zip dosyaları da yayınlanabilir. Bunun da ötesinde, akış yalnızca dosyalarla sınırlı değildir. HTTP, FTP, SSH bağlantıları ve Giriş / Çıkış da yayınlanabilir.


Vikipedi Akış kavramı hakkında ne diyor?

Bilgisayar biliminde, bir akış zaman içinde kullanıma sunulan bir dizi veri öğesidir. Bir akış, bir konveyör bandındaki nesnelerin büyük partiler yerine birer birer işlenmesi olarak düşünülebilir.

Bkz . Https://en.wikipedia.org/wiki/Stream_%28computing%29 .

Wikipedia buna bağlantı veriyor: https://srfi.schemers.org/srfi-41/srfi-41.html ve yazarlar akışlar hakkında şunları söylüyor:

Bazen tembel listeler olarak adlandırılan akışlar, yalnızca istek üzerine hesaplanan öğeleri içeren sıralı bir veri yapısıdır. Bir akış ya boştur ya da cdr'sinde bir akış bulunan bir çifttir. Bir akışın elemanları yalnızca erişildiğinde hesaplandığından, akışlar sonsuz olabilir.

Dolayısıyla bir Akış aslında bir veri yapısıdır.


Sonucum: Akış, sıralı bir şekilde okunabilen veya bunlara yazılabilen veriler içeren bir kaynaktır. Bir akış kaynağın içerdiği her şeyi bir kerede okumaz, sırayla okur / yazar.


Yararlı bağlantılar:

  1. http://www.slideshare.net/auroraeosrose/writing-and-using-php-streams-and-sockets-zendcon-2011 Çok net bir sunum sağlar
  2. https://www.sk89q.com/2010/04/introduction-to-php-streams/
  3. http://www.netlingo.com/word/stream-or-streaming.php
  4. http://www.brainbell.com/tutorials/php/Using_PHP_Streams.htm
  5. http://www.sitepoint.com/php-streaming-output-buffering-explained/
  6. http://php.net/manual/en/wrappers.php
  7. http://www.digidata-lb.com/streaming/Streaming_Proposal.pdf
  8. http://www.webopedia.com/TERM/S/streaming.html
  9. https://en.wikipedia.org/wiki/Stream_%28computing%29
  10. https://srfi.schemers.org/srfi-41/srfi-41.html

4

Bu sadece bir konsept, hayatınızı kolaylaştıran bir başka soyutlama seviyesi. Ve hepsinin ortak arayüzü var, bu da onları bir boru şeklinde birleştirebileceğiniz anlamına geliyor. Örneğin, base64 kodlayın, sonra zip ve bunu diske ve hepsi bir satırda yazın!


Bu kesinlikle yararlı, ama bunun "bütün mesele" olduğunu söyleyemem. Zincir olmadan bile ortak bir soyutlamaya sahip olmak yararlıdır.
Jon Skeet

Evet, haklısın. Bunu açıklığa kavuşturmak için kelimeleri değiştirdim.
vava

Evet, bu daha iyi. Umarım çok seçici olduğumu düşünmedin!
Jon Skeet

3

Gördüğüm akışların en iyi açıklaması SICP'nin 3. bölümüdür . (Mantıklı olması için ilk 2 bölümü okumanız gerekebilir, ama yine de yapmanız gerekir. :-)

Baytlar için steram kullanmazlar, tamsayılar kullanırlar. Ondan aldığım en önemli noktalar:

  • Akışlar gecikmeli listelerdir
  • Hesaplama yükü [bazı durumlarda vaktinde her şeyi hevesle hesaplamak] çirkin
  • Sınırsız uzunlukta dizileri temsil etmek için akışları kullanabiliriz

Şu anda SICP'in 1. bölümünde bulunuyorum. Teşekkürler!
Rob Sobers

2
biri diğerlerinden SICP akışını anlatmak ister . önemli bir özelliği SICP akışı olan laziness genel süre, akış kavramı vurgulamaktadır soyutlama ilgili veri sekansları .
道 嘉 道

2

Başka bir nokta (Dosya durumunu okumak için):

  1. streamdaha önce başka bir şey yapmanıza izin verebilir finished reading all content of the file.
  2. tüm dosya içeriğini aynı anda yüklemeniz gerekmediğinden bellek tasarrufu yapabilirsiniz.

1

Akışları soyut bir veri kaynağı (bayt, karakter vb.) Olarak düşünün. Bir ağ soketi, bir diskteki dosya veya web sunucusundan gelen bir yanıt olsun, somut veri kaynağından okuma ve yazma için gerçek mekaniği soyutlarlar.


1

Bence, destek mağazasının kendisinin genellikle sadece bir soyutlama olduğunu düşünmelisiniz. Bir bellek akışının anlaşılması oldukça kolaydır, ancak kullandığınız dosya sistemine bağlı olarak bir dosya kökten farklıdır, kullandığınız sabit sürücüyü boş verin. Tüm akışlar aslında bir destek mağazasının üstünde yer almaz: ağ akışları hemen hemen akışlardır.

Bir akışın noktası, dikkatimizi önemli olanla sınırlandırmamızdır. Standart bir soyutlamaya sahip olarak, ortak işlemler gerçekleştirebiliriz. Örneğin, bugün URL'ler için bir dosya veya HTTP yanıtı aramak istemeseniz bile, yarın istemeyeceğiniz anlamına gelmez.

Akımlar başlangıçta bellek depolama ile karşılaştırıldığında çok küçük olduğunda tasarlandı. Sadece bir C dosyasını okumak önemli bir yük olabilir. Bellek ayak izini en aza indirmek son derece önemliydi. Bu nedenle, çok az yüklenmesi gereken bir soyutlama çok faydalı oldu. Bugün, ağ iletişimi yaparken eşit derecede yararlıdır ve dosyalar ile uğraşırken nadiren bu kısıtlayıcıdır. Arabelleğe alma gibi şeyleri genel bir şekilde şeffaf bir şekilde ekleme yeteneği, onu daha da kullanışlı hale getirir.


0

Akış, bir bayt dizisinin soyutlanmasıdır. Fikir, baytların nereden geldiğini bilmenize gerek yoktur, sadece standart bir şekilde okuyabilirsiniz.

Örneğin, verileri bir akış yoluyla işlerseniz, verilerin bir dosyadan, ağ bağlantısından, bir dizeden, veritabanındaki bir damladan vb. Gelmesi, kodunuz için önemli değildir.

Destek mağazasının kendisiyle etkileşimde bulunmakla ilgili yanlış bir şey yoktur, ancak destek mağazasının uygulamasına bağlanması dışında.


0

Akış, verilerle etkileşim için standart yöntemler ve özellikler kümesi sağlayan bir soyutlamadır. Gerçek depolama ortamından soyutlanarak, kodunuz o ortamın ne olduğuna ve hatta bu ortamın uygulanmasına tamamen güvenmeden yazılabilir.

İyi bir benzetme bir çanta düşünmek olabilir. Çanta bir çanta yapma işini gerçekleştirdiği ve eşyalarınızı geri alabildiği sürece, bir çantanın ne yapıldığını ya da eşyalarınızı koyduğunuzda ne yaptığı umrunda değil. Bir akış, depolama ortamı için torba kavramının bir torbanın farklı örnekleri (çöp torbası, el çantası, sırt çantası vb.) İçin tanımladığı şeyi tanımlar - etkileşim kuralları.


0

Kısa tutacağım, burada sadece kelimeyi kaçırıyordum:

Akışlar genellikle her türlü veri içeren tamponda depolanan kuyruklardır .

(Şimdi, hepimiz sıraların ne olduğunu bildiğimiz için, bunu daha fazla açıklamaya gerek yok.)

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.