Mengapa menulis ke Stream dalam beberapa bagian?

Saya bertanya-tanya mengapa begitu banyak contoh membaca array byte ke dalam aliran di chuck dan tidak semuanya sekaligus... Saya tahu ini adalah pertanyaan yang lembut, tapi saya tertarik.

Saya mengerti sedikit tentang perangkat keras dan pengisian buffer bisa sangat bergantung pada ukuran dan Anda tidak ingin menulis ke buffer lagi sampai buffer tersebut dipindahkan ke mana pun ia harus pergi, dll... tetapi dengan platform .Net (dan lainnya bahasa modern) Saya melihat contoh keduanya. Jadi kapan menggunakan yang mana dan kapan, atau yang kedua mutlak tidak, tidak?

Inilah hal (kode) yang saya maksud:

var buffer = new byte[4096];

while (true)
{
    var read = this.InputStream.Read(buffer, 0, buffer.Length);

    if (read == 0)
        break;

    OutputStream.Write(buffer, 0, read);
}

daripada:

var buffer = new byte[InputStream.Length];

var read = this.InputStream.Read(buffer, 0, buffer.Length);

OutputStream.Write(buffer, 0, read);

Saya yakin keduanya legal? Jadi mengapa harus melalui semua keributan dari loop while (apa pun yang Anda putuskan untuk menyusunnya)?

Saya bermain sebagai pendukung setan di sini karena saya ingin belajar sebanyak yang saya bisa :)


person tigerswithguitars    schedule 28.11.2012    source sumber


Jawaban (4)


Dalam kasus pertama, yang Anda butuhkan hanyalah memori 4kB. Dalam kasus kedua, Anda memerlukan memori sebanyak yang dibutuhkan aliran data masukan. Jika aliran input 4GB, Anda memerlukan 4GB.

Apakah menurut Anda akan lebih baik jika operasi penyalinan file memerlukan RAM 4 GB? Bagaimana jika Anda menyiapkan image disk sebesar 20 GB?

Ada juga yang menggunakan pipa. Anda tidak sering menggunakannya di Windows, namun kasus serupa sering terlihat di sistem operasi lain. Kasus kedua menunggu semua data dibaca, dan baru kemudian menuliskannya ke output. Namun, terkadang disarankan untuk menulis data sesegera mungkin—kasus pertama akan mulai menulis ke aliran keluaran segera setelah masukan 4kB pertama dibaca. Bayangkan menyajikan halaman web: disarankan bagi server web untuk mengirim data sesegera mungkin, sehingga browser web klien akan mulai merender header dan bagian pertama konten, bukan menunggu keseluruhan isi.

Namun, jika Anda mengetahui bahwa aliran input tidak akan lebih besar dari 4kB, maka kedua kasus tersebut setara.

person liori    schedule 28.11.2012
comment
Kasus umum, jumlah yang Anda simpan di memori lebih penting, oleh karena itu jika Anda mengisi buffer (stream) dan tidak memindahkannya, itu buruk. Katakanlah jika kita mengeluarkan OutputStream dari persamaan dan hanya mengisi InputStream dengan perulangan while? Karena saya juga pernah melihat ini, apakah itu sama buruknya dengan contoh kedua? - person tigerswithguitars; 28.11.2012
comment
Itu semua tergantung pada kasus spesifik Anda, pada apa yang ingin Anda lakukan. Ada algoritma yang dapat beroperasi pada potongan kecil (menghitung jumlah nilai, mencari nilai maksimum), dan ada algoritma yang membutuhkan semua data (misalnya: pengurutan). Dalam kasus kedua, perlu membaca semua data. Dalam kasus pertama—tidak juga. - person liori; 28.11.2012
comment
Keren... jadi ini spesifik untuk aplikasi, yang merupakan pemikiran utama saya, menurut saya... daripada sifat objek itu sendiri di sebagian besar bahasa. Terima kasih :) - person tigerswithguitars; 28.11.2012

Terkadang, InputStream.Length tidak valid untuk beberapa sumber, misalnya dari net transport, atau buffernya mungkin besar, misalnya membaca dari file yang sangat besar. menurutku.

person Healer    schedule 28.11.2012
comment
Itu poin yang sangat bagus... Aku belum memikirkan kemungkinan itu. Tapi itu sangat masuk akal, terutama jika Anda dekat dengan metal dan membaca untuk buffer menerima informasi! - person tigerswithguitars; 28.11.2012
comment
+1 ... andai saja bisa + 2. Saya ingin menerima jawaban ini karena Anda memasukkan sesuatu yang bahkan tidak terpikirkan oleh saya sama sekali, dengan cara yang sangat sederhana. Itu selalu keren. Namun demi kepentingan Komunitas SO, yang terbaik adalah menerima jawaban yang bermanfaat bagi banyak orang. - person tigerswithguitars; 28.11.2012

Ini melindungi Anda dari situasi di mana aliran input Anda panjangnya beberapa gigabyte.

person Joe    schedule 28.11.2012
comment
Apa yang dimaksud dengan perlindungan? Mengapa Anda membutuhkannya? - person tigerswithguitars; 28.11.2012
comment
Perlindungan terhadap, misalnya, OutOfMemoryException. - person Joe; 28.11.2012
comment
Benar. Jika Anda membaca file, katakanlah, ke dalam memori yang lebih besar dari yang dapat diakses oleh aplikasi. Diberikan. Namun hal ini mungkin terjadi pada data dalam jumlah besar. Jadi pola yang tebal tidak melindungi hal ini, hanya membuang buffer ke aliran keluaran dan mendaur ulang. - person tigerswithguitars; 28.11.2012
comment
@tigerswithguitars - Jadi potongan polanya tidak melindungi hal ini - tentu saja. Anda hanya memerlukan buffer dengan ukuran yang dikonfigurasi (4096) dalam contoh Anda, daripada buffer yang ukurannya sebesar aliran input. - person Joe; 28.11.2012
comment
Keren, saya mengerti... tetapi Anda hanya memiliki sebagian dari keseluruhan file yang Anda inginkan, bukan? Jadi, Anda harus melakukan rekayasa perangkat lunak yang sebenarnya dan memastikan hal ini tidak membuat dunia runtuh (ed - aplikasi mati)! :P - person tigerswithguitars; 28.11.2012
comment
@tigerswithguitars, tetapi Anda hanya memiliki sebagian dari seluruh file yang Anda inginkan dengan benar - tidak, Anda akan mendapatkan seluruh file disalin dari aliran input ke aliran output sedikit demi sedikit. Kebetulan, dengan .NET 4 atau lebih baru, Anda cukup menggunakan InputStream.CopyTo(OutputStream), yang menggunakan ukuran buffer default, atau misalnya. InputStream.CopyTo(OutputStream, 4096) yang memungkinkan Anda menentukan ukuran buffer. - person Joe; 28.11.2012

Anda tidak tahu berapa banyak data yang Read mungkin kembalikan. Hal ini dapat menimbulkan masalah kinerja yang besar jika Anda membaca file yang sangat besar.

Jika Anda memiliki kendali atas input, dan yakin ukurannya masuk akal, maka Anda pasti dapat membaca seluruh array sekaligus. Namun berhati-hatilah jika pengguna dapat memberikan masukan yang sewenang-wenang.

person Jon B    schedule 28.11.2012