Apa metode yang lebih disukai untuk membuat array byte dari aliran input?
Berikut adalah solusi saya saat ini dengan .NET 3.5.
Stream s;
byte[] b;
using (BinaryReader br = new BinaryReader(s))
{
b = br.ReadBytes((int)s.Length);
}
Apakah masih lebih baik untuk membaca dan menulis potongan-potongan aliran?
c#
.net-3.5
inputstream
Bob
sumber
sumber
Jawaban:
Itu benar-benar tergantung pada apakah Anda bisa percaya atau tidak
s.Length
. Untuk banyak aliran, Anda tidak tahu berapa banyak data yang akan ada. Dalam kasus seperti itu - dan sebelum .NET 4 - Saya akan menggunakan kode seperti ini:Dengan .NET 4 dan di atasnya, saya akan menggunakan
Stream.CopyTo
, yang pada dasarnya setara dengan loop dalam kode saya - buatMemoryStream
, panggilstream.CopyTo(ms)
dan kembalilahms.ToArray()
. Pekerjaan selesai.Saya mungkin harus menjelaskan mengapa jawaban saya lebih panjang dari yang lain.
Stream.Read
tidak menjamin bahwa itu akan membaca semua yang diminta. Jika Anda membaca dari aliran jaringan, misalnya, ia mungkin membaca nilai satu paket dan kemudian kembali, bahkan jika akan ada lebih banyak data segera.BinaryReader.Read
akan terus berjalan hingga akhir streaming atau ukuran yang Anda tentukan, tetapi Anda masih harus tahu ukuran untuk memulai.Metode di atas akan terus membaca (dan menyalin ke a
MemoryStream
) sampai kehabisan data. Kemudian memintaMemoryStream
untuk mengembalikan salinan data dalam array. Jika Anda tahu ukuran untuk memulai - atau berpikir Anda tahu ukurannya, tanpa yakin - Anda bisa membuatMemoryStream
menjadi ukuran itu. Demikian juga Anda dapat memberi tanda centang di akhir, dan jika panjang aliran adalah ukuran yang sama dengan buffer (dikembalikan olehMemoryStream.GetBuffer
) maka Anda bisa mengembalikan buffer. Jadi kode di atas tidak cukup dioptimalkan, tetapi setidaknya akan benar. Itu tidak memikul tanggung jawab untuk menutup aliran - penelepon harus melakukan itu.Lihat artikel ini untuk info lebih lanjut (dan implementasi alternatif).
sumber
16*1024
secara spesifik?Sementara jawaban Jon benar, dia menulis ulang kode yang sudah ada di
CopyTo
. Jadi untuk .Net 4 gunakan solusi Sandip, tetapi untuk versi .Net sebelumnya gunakan jawaban Jon. Kode Sandip akan ditingkatkan dengan menggunakan "menggunakan" sebagai pengecualian dalamCopyTo
, dalam banyak situasi, sangat mungkin dan akan meninggalkan yangMemoryStream
tidak dibuang.sumber
input
sudah terjadiMemorySteam
dan korsleting. Saya tahu itu akan bodoh dari penelepon untuk lulusMemoryStream
tetapi ...MemoryStream
maka apakah pengoptimalan tersebut masuk akal dalam konteks Anda adalah perbandingan waktu yang diperlukan untuk melakukan jutaan konversi jenis dengan waktu yang diperlukan untuk menyalin aliran yang menjadiMemoryStream
sasaran lainMemoryStream
.Hanya ingin menunjukkan bahwa seandainya Anda memiliki MemoryStream yang sudah Anda miliki
memorystream.ToArray()
untuk itu.Juga, jika Anda berurusan dengan aliran subtipe yang tidak diketahui atau berbeda dan Anda dapat menerima
MemoryStream
, Anda dapat menyampaikan pada metode tersebut untuk kasus tersebut dan masih menggunakan jawaban yang diterima untuk yang lain, seperti ini:sumber
MemoryStream
s. Tentu saja contohnya juga jelas tidak lengkap, dalam cara menggunakan variabel yang tidak diinisialisasi.stream.Seek(1L, SeekOrigin.Begin)
, sebelum Anda memanggilnya dengan mudah, jika alirannya adalah aliran memori, Anda akan mendapatkan 1 byte lebih banyak daripada jika itu adalah aliran lainnya. Jika penelepon mengharapkan untuk membaca dari mana posisi saat ini ke akhir aliran maka Anda tidak boleh menggunakanCopyTo
atauToArray()
; Dalam kebanyakan kasus ini tidak akan menjadi masalah, tetapi jika penelepon tidak tahu tentang perilaku aneh ini mereka akan bingung.sumber
hanya pasangan saya sen ... praktik yang sering saya gunakan adalah mengatur metode seperti ini sebagai pembantu kustom
tambahkan namespace ke file konfigurasi dan gunakan di mana saja Anda inginkan
sumber
CopyTo
tidak tersediaStream
hingga 4.0.Anda cukup menggunakan metode ToArray () dari kelas MemoryStream, untuk contoh
sumber
Anda bahkan dapat membuatnya lebih mewah dengan ekstensi:
Dan kemudian menyebutnya sebagai metode biasa:
sumber
Saya mendapatkan kesalahan waktu kompilasi dengan kode Bob (yaitu si penanya). Stream.Length adalah panjang sedangkan BinaryReader.ReadBytes mengambil parameter integer. Dalam kasus saya, saya tidak berharap berurusan dengan Streaming yang cukup besar sehingga membutuhkan ketelitian yang lama, jadi saya menggunakan yang berikut ini:
sumber
Jika ada yang suka, ini adalah solusi .NET 4+ saja yang dibentuk sebagai metode ekstensi tanpa perlu Buang panggilan di MemoryStream. Ini adalah optimasi sepele yang sia-sia, tetapi perlu dicatat bahwa gagal untuk Membuang MemoryStream bukanlah kegagalan nyata.
sumber
Yang di atas tidak apa-apa ... tetapi Anda akan menemukan korupsi data ketika Anda mengirim barang melalui SMTP (jika perlu). Saya telah mengubah ke hal lain yang akan membantu mengirimkan byte ke byte dengan benar: '
sumber
Buat kelas pembantu dan rujuk di mana saja Anda ingin menggunakannya.
sumber
Di namespace RestSharp.Extensions ada metode ReadAsBytes. Di dalam metode ini digunakan MemoryStream dan ada kode yang sama seperti pada beberapa contoh di halaman ini tetapi ketika Anda menggunakan RestSharp ini adalah cara termudah.
sumber
Anda dapat menggunakan metode ekstensi ini.
sumber
Ini adalah fungsi yang saya gunakan, diuji dan bekerja dengan baik. harap diingat bahwa 'input' tidak boleh nol dan 'input.position' harus direset ke '0' sebelum membaca jika tidak maka akan merusak loop baca dan tidak ada yang akan membaca untuk mengkonversi ke array.
sumber
sumber
saya dapat membuatnya bekerja pada satu baris:
seperti yang diklarifikasi oleh johnnyRose , kode di atas hanya akan berfungsi untuk MemoryStream
sumber
localStream
bukanMemoryStream
? Kode ini akan gagal.localStream
untukMemoryStream
, tetapilocalStream
adalah tidak satuMemoryStream
, itu akan gagal. Kode ini akan dikompilasi dengan baik, tetapi bisa gagal saat runtime, tergantung pada tipe aktuallocalStream
. Anda tidak selalu bisa secara sewenang-wenang melemparkan tipe dasar ke tipe anak; baca lebih lanjut di sini . Ini adalah contoh bagus lainnya yang menjelaskan mengapa Anda tidak selalu bisa melakukan ini.