C # akışları kullanma


116

Akışlar benim için biraz gizemli. Hangi akışı ne zaman ve nasıl kullanacağımı bilmiyorum. Birisi bana akışların nasıl kullanıldığını açıklayabilir mi?

Doğru anlarsam, üç akış türü vardır:

  • stream
  • read stream
  • write stream

Bu doğru mu? Ve örneğin, a Memorystreamve a arasındaki fark FileStreamnedir?


13
Eğer kontrol etmek isteyebilirsiniz stackoverflow.com/questions/507747/...
Preets

3
Bir bayt dizisi alın ve ardından bunun için Streamokuma, yazma ve konum değiştirme gibi bazı yararlı yöntemleri ortaya çıkaran bir sarmalayıcı oluşturun ( ). Artık Stream, belirli bir destek deposuna dayalı olarak bu işlevsellikten miras alan ve bu işlevsellik üzerine inşa edilen destek depolarına (FileStream, MemoryStream) dayalı sınıflar oluşturabilirsiniz .
The Muffin Man

Yanıtlar:


80

Bir akış veri aktarımı için kullanılan bir amacıdır. System.IO.StreamNET'teki diğer tüm akış sınıflarının türetildiği genel bir akış sınıfı vardır. StreamSınıf bayt ilgilenir.

Somut akış sınıfları, bayt dışındaki diğer veri türleriyle ilgilenmek için kullanılır. Örneğin:

  • FileStreamDış kaynak bir dosya olduğunda sınıf kullanılır
  • MemoryStream verileri hafızaya kaydetmek için kullanılır
  • System.Net.Sockets.NetworkStream ağ verilerini işler

Okuyucu / yazıcı akışları, akışlar gibi StreamReaderve StreamWriterdeğillerdir - türetilmezler, System.IO.Streamveri akışından veri yazmaya ve okumaya yardımcı olmak için tasarlanmıştır!


3
Dolayısıyla, doğru anlarsam, akış verileri içerir ve onunla hiçbir şey yapmaz. Okuyucu ve yazar 'yardımcı' sınıfları, akış içindeki verileri işleyebilir (değiştirebilir).
Martijn

9
Hayır, Stream veri konteyneri değildir, veri aktarımı için kullanılır, örneğin FileStream verileri bayttan [] fiziksel dosyaya aktarır, NetworkStream bayt [] soket ile aktarır. Reader Writer sınıfları, akıştan yazmak ve okumak için yardımcı sınıflardır; örneğin StreamReader, [] bayt değil Akış dizesinden okumak için kullanılabilir. FileStream'i bir parametre olarak verirseniz, FileStream soketten ise, File'dan okuyacaktır.
Arsen Mkrtchyan

ayrıca, StreamReader ve StreamWriter TEXT (karakter) akışlarını okumak ve yazmak içindir.
1c1cle

1
MemoryStream'i anlamanıza yardımcı olacak iyi bir makale var. codeproject.com/Articles/832387/…
Jiaji Li

2
@ user420667. iyi soru. Hem AudioStream hem de TemperatureStream durumunda, bunlar büyük olasılıkla aygıtla ilişkili sürücüye BinaryStreams olacaktır. Ya da, arayüz için özel olarak oluşturulmuş bir CustomStream oluşturabilirsiniz.
1c1cle

62

Buradaki diğer yanıtları biraz genişletmek ve noktalı olarak göreceğiniz örnek kodların çoğunu açıklamaya yardımcı olmak için, çoğu zaman doğrudan bir akışı okuyup yazmazsınız. Akışlar, veri aktarımı için düşük seviyeli bir araçtır.

Okuma ve yazma işlevlerinin tamamının bayt yönelimli olduğunu fark edeceksiniz, örneğin WriteByte (). Tamsayılar, dizgiler vb. İle uğraşmak için hiçbir işlev yoktur. Bu, akışı çok genel amaçlı yapar, ancak, örneğin, sadece metni aktarmak istiyorsanız, üzerinde çalışmayı daha az basit hale getirir.

Ancak .NET, yerel türler ve düşük düzey akış arabirimi arasında dönüşüm sağlayan ve verileri sizin için akışa veya akıştan aktaran sınıflar sağlar. Bazı dikkate değer sınıflar şunlardır:

StreamWriter // Badly named. Should be TextWriter.
StreamReader // Badly named. Should be TextReader.
BinaryWriter
BinaryReader

Bunları kullanmak için önce akışınızı alırsınız, ardından yukarıdaki sınıflardan birini oluşturursunuz ve bunu akışla ilişkilendirirsiniz. Örneğin

MemoryStream memoryStream = new MemoryStream();
StreamWriter myStreamWriter = new StreamWriter(memoryStream);

StreamReader ve StreamWriter yerel türler ve bunların dize temsilleri arasında dönüşüm yapar ve ardından dizeleri bayt olarak akışa ve akıştan aktarır. Yani

myStreamWriter.Write(123);

akışa "123" (üç karakter '1', '2' ve ardından '3') yazar. Metin dosyalarıyla (örneğin html) uğraşıyorsanız, StreamReader ve StreamWriter kullanacağınız sınıflardır.

Buna karşılık

myBinaryWriter.Write(123);

32 bitlik tamsayı değeri 123'ü (0x7B, 0x00, 0x00, 0x00) temsil eden dört bayt yazar. İkili dosyalar veya ağ protokolleri ile uğraşıyorsanız, BinaryReader ve BinaryWriter kullanabilirsiniz. (Ağlar veya diğer sistemlerle veri alışverişi yapıyorsanız, bitkinliğe dikkat etmeniz gerekir , ancak bu başka bir gönderi.)


StreamWriter ve Reader adaptör sınıfları ciddi şekilde kötü adlandırılmıştır. Bundan bahsettiğin için teşekkürler. Nasıl oldu da bu isimle ortaya çıktıkları benim için hala şaşırtıcı.
Tarık

Ayrıca, ikili yazar ve okuyucu sınıfları bile kötü adlandırılmıştır.
Tarık

22

Akışlar, büyük miktarda veriyle uğraşmak için iyidir. Tüm verileri aynı anda belleğe yüklemek pratik olmadığında, onu bir akış olarak açabilir ve küçük parçalarla çalışabilirsiniz.


1
"Küçük parçalarla çalışın" dediğiniz şeyin bir örneğini görmek isterim.
Jenna Leaf

2
Akışlar, küçük miktarlarda veri için de iyidir. Bir C # programcısı bir dosyanın içeriğini değiştirmek isterse, veri miktarına bakılmaksızın akışları kullanmalıdır. Aynı ifade ağ akışları için de geçerlidir. Kabul edilirse, programcı C gibi daha düşük seviyeli bir dil ise, o zaman karakterleri veya baytları doğrudan bir diske veya sokete yazmak mümkündür, ancak az miktarda veri için bile, zaman alıcıdır ve daha fazla hata.
1c1cle

10

Akış, bir physicalbayt akışı üzerinde yalnızca bir soyutlamadır (veya sarmalayıcıdır) . Bu physicalakışa base stream. Dolayısıyla, üzerinde bir akış sarmalayıcısının oluşturulduğu bir temel akış vardır ve bu nedenle sarmalayıcı, temel akış türünden, yani FileStream, MemoryStreamvb.

Akış sarmalayıcısının avantajı, herhangi bir temel türdeki akışlarla etkileşim kurmak için birleşik bir API elde etmenizdir usb, file.

Verileri neden akış olarak ele alasınız - veri yığınları isteğe bağlı olarak yüklendiği için, tüm verileri belleğe yüklemek yerine verileri parçalar halinde inceleyebilir / işleyebiliriz. Bu, programların çoğunun, örneğin bir işletim sistemi görüntü dosyasını şifrelemek gibi büyük dosyalarla nasıl başa çıktığını gösterir.


4

Yalnızca bir temel türü vardır Stream. Bununla birlikte, çeşitli durumlarda, bazı üyeler çağrıldığında bir istisna atar çünkü bu bağlamda işlem mevcut değildir.

Örneğin a MemoryStream, baytları bir bellek parçasının içine ve dışına taşımanın bir yoludur. Böylece Oku ve Yaz'ı arayabilirsin.

Öte yandan a FileStream, bir dosyadan / dosyadan okumanıza veya yazmanıza (veya her ikisine birden) izin verir. Gerçekte Okuma veya Yazma yapıp yapamayacağınız dosyanın nasıl açıldığına bağlıdır. Bir dosyaya sadece Okuma erişimi için açtıysanız yazamazsınız.


3

MSDN'de akışları okuyarak başlayabilirim: http://msdn.microsoft.com/en-us/library/system.io.stream.aspx

Memorystream ve FileStream, sırasıyla ham bellek ve Dosyalar ile çalışmak için kullanılan akışlardır ...


Bağlantı için teşekkürler. "Çevrimiçi kaynak koduna göz atabilir, referansı çevrimdışı görüntüleme için indirebilir ve hata ayıklama sırasında kaynaklarda (yamalar ve güncellemeler dahil) ilerleyebilirsiniz" diye sevdim. Bu özellik yeni bir içgörü düzeyi sunar.
David

1

Ben bunlara farklı türden akışlar demezdim. Stream sınıfı, belirli bir akışın okunup yazılamayacağını size söyleyen CanRead ve CanWrite özelliklerine sahiptir.

Farklı akış sınıfları (MemoryStream ve FileStream gibi) arasındaki en büyük fark, verilerin okunduğu veya nereye yazıldığı yedekleme deposudur. Adından da anlaşılıyor. Bir MemoryStream, verileri yalnızca bellekte depolar, bir FileStream diskteki bir dosyayla yedeklenir, bir NetworkStream ağdan verileri okur vb.

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.