Создание байтового массива из потока

Каков предпочтительный метод создания массива 9X_.cs-file байтов из входного потока?

Вот мое текущее 9X_c# решение с .NET 3.5.

Stream s; byte[] b; using (BinaryReader br = new BinaryReader(s)) { b = br.ReadBytes((int)s.Length); } 

Лучше ли читать и записывать 9X_inputstream фрагменты потока?

1045
2

  • Конечно, другой вопрос: * следует ли * создавать byte [] из потока ... для боль ...
17
Общее количество ответов: 17

Ответ #1

Ответ на вопрос: Создание байтового массива из потока

Это действительно зависит от того, доверяете 9X_.net-3.5 ли вы s.Length. Для многих потоков вы просто не 9X_.net-framework-3.5 знаете, сколько будет данных. В таких случаях 9X_.cs-file - и до .NET 4 - я бы использовал такой код:

public static byte[] ReadFully(Stream input) { byte[] buffer = new byte[16*1024]; using (MemoryStream ms = new MemoryStream()) { int read; while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); } return ms.ToArray(); } } 

В 9X_c#.net .NET 4 и выше я бы использовал Stream.CopyTo, который 9X_c-sharp в основном эквивалентен циклу в моем коде 9X_c#-language - создайте MemoryStream, вызовите stream.CopyTo(ms) и затем верните ms.ToArray(). Работа 9X_framework3.5 сделана.

Возможно, мне стоит объяснить, почему 9X_.net-framework-3.5 мой ответ длиннее других. Stream.Read не гарантирует, что 9X_c#-language он прочитает все, о чем его просят. Например, если 9X_framework3.5 вы читаете из сетевого потока, он может 9X_.net-3.5 прочитать стоимость одного пакета и затем 9X_c-sharp вернуться, даже если скоро будет больше 9X_c-sharp данных. BinaryReader.Read будет продолжаться до конца потока 9X_csharp или до указанного вами размера, но вам все 9X_visual-c# равно нужно знать размер для начала.

Вышеупомянутый 9X_.net-framework-3.5 метод будет продолжать чтение (и копирование 9X_inputstream в MemoryStream) до тех пор, пока не закончатся данные. Затем 9X_.net-framework-3.5 он просит MemoryStream вернуть копию данных в массиве. Если 9X_csharp вы знаете размер для начала - или думаете, что 9X_inputstream знаете размер, но не уверены - вы можете 9X_visual-c# сконструировать MemoryStream для начала этого размера. Точно 9X_c#.net так же вы можете поставить галочку в конце, и 9X_csharp если длина потока равна размеру буфера (возвращенному 9X_.cs-file MemoryStream.GetBuffer), вы можете просто вернуть буфер. Таким 9X_.cs-file образом, приведенный выше код не совсем 9X_c-sharp оптимизирован, но, по крайней мере, будет 9X_framework3.5 правильным. Он не несет ответственности 9X_visual-c# за закрытие потока - это должен сделать 9X_.cs-file вызывающий.

См. this article для получения дополнительной 9X_inputstream информации (и альтернативной реализации).

1415
8

  • @just_name В реализации монопроекта также используется `10 * 1024`.< ...

Ответ #2

Ответ на вопрос: Создание байтового массива из потока

Хотя ответ Джона правильный, он переписывает 9X_c#.net код, который уже существует в CopyTo. Итак, для 9X_.net-framework-3.5 .Net 4 используйте решение Sandip, но для 9X_inputstream предыдущей версии .Net используйте ответ 9X_c#-language Джона. Код Сэндипа можно было бы улучшить, используя 9X_.net-3.5 "using", поскольку исключения в CopyTo во многих 9X_c#-language ситуациях весьма вероятны и оставят MemoryStream не 9X_framework3.5 удаленным.

public static byte[] ReadFully(Stream input) { using (MemoryStream ms = new MemoryStream()) { input.CopyTo(ms); return ms.ToArray(); } } 

846
6

  • Чем отличается ваш ответ от ответа Джона? Также я должен сделать это ...

Ответ #3

Ответ на вопрос: Создание байтового массива из потока

Просто хочу отметить, что если у вас есть 9X_.net-3.5 MemoryStream, у вас уже есть memorystream.ToArray() для этого.

Кроме 9X_c#-language того, если вы имеете дело с потоками неизвестных 9X_inputstream или разных подтипов и можете получить MemoryStream, вы 9X_inputstream можете использовать указанный метод для 9X_inputstream этих случаев и по-прежнему использовать 9X_csharp принятый ответ для других, например:

public static byte[] StreamToByteArray(Stream stream) { if (stream is MemoryStream) { return ((MemoryStream)stream).ToArray(); } else { // Jon Skeet's accepted answer return ReadFully(stream); } } 

126
3

  • Это фактически вносит ошибку в код Skeet; Если вы вызываете stream.Seek (1L, SeekOrigin.Begin), перед тем, как вы вызываете его, если поток является потоком памяти, вы получите на 1 байт больше, чем если ...

Ответ #4

Ответ на вопрос: Создание байтового массива из потока

MemoryStream ms = new MemoryStream(); file.PostedFile.InputStream.CopyTo(ms); var byts = ms.ToArray(); ms.Dispose(); 
9X_inputstream
75
1

  • MemoryStream следует создавать с по ...

Ответ #5

Ответ на вопрос: Создание байтового массива из потока

всего пара центов ... практика, которую 9X_inputstream я часто использую, состоит в том, чтобы 9X_inputstream организовать такие методы как пользовательский 9X_.net-framework-3.5 помощник

public static class StreamHelpers { public static byte[] ReadFully(this Stream input) { using (MemoryStream ms = new MemoryStream()) { input.CopyTo(ms); return ms.ToArray(); } } } 

добавьте пространство имен в файл 9X_.net-3.5 конфигурации и используйте его где угодно

55
1

  • Обратите внимание, что это не будет работать в .NET 3.5 и ниже, поскольку CopyTo не б ...

Ответ #6

Ответ на вопрос: Создание байтового массива из потока

Вы можете просто использовать метод ToArray() класса 9X_visual-c# MemoryStream, например,

MemoryStream ms = (MemoryStream)dataInStream; byte[] imageBytes = ms.ToArray(); 

20
1

  • это будет работать, только есл ...

Ответ #7

Ответ на вопрос: Создание байтового массива из потока

Вы можете даже сделать его более привлекательным 9X_.net-framework-3.5 с помощью расширений:

namespace Foo { public static class Extensions { public static byte[] ToByteArray(this Stream stream) { using (stream) { using (MemoryStream memStream = new MemoryStream()) { stream.CopyTo(memStream); return memStream.ToArray(); } } } } } 

А затем вызовите его 9X_.net-3.5 как обычный метод:

byte[] arr = someStream.ToByteArray() 

14
1

  • Я думаю, что помещать входной поток в блок using - плохая идея. Эта ответственно ...

Ответ #8

Ответ на вопрос: Создание байтового массива из потока

Я получаю ошибку времени компиляции с кодом 9X_inputstream Боба (то есть спрашивающего). Stream.Length 9X_c#.net является длинным, тогда как BinaryReader.ReadBytes 9X_framework3.5 принимает целочисленный параметр. В моем 9X_inputstream случае я не ожидаю, что буду иметь дело 9X_.net-3.5 с потоками, достаточно большими, чтобы требовать 9X_inputstream большой точности, поэтому я использую следующее:

Stream s; byte[] b; if (s.Length > int.MaxValue) { throw new Exception("This stream is larger than the conversion algorithm can currently handle."); } using (var br = new BinaryReader(s)) { b = br.ReadBytes((int)s.Length); } 

8
0

Ответ #9

Ответ на вопрос: Создание байтового массива из потока

Если кому-то это нравится, вот решение только 9X_c#-language для .NET 4+, сформированное как метод расширения 9X_c# без ненужного вызова Dispose в MemoryStream. Это 9X_inputstream безнадежно тривиальная оптимизация, но стоит 9X_c#.net отметить, что отказ от Dispose a MemoryStream 9X_.net-3.5 не является настоящим провалом.

public static class StreamHelpers { public static byte[] ReadFully(this Stream input) { var ms = new MemoryStream(); input.CopyTo(ms); return ms.ToArray(); } } 

8
0

Ответ #10

Ответ на вопрос: Создание байтового массива из потока

То, что указано выше, подходит ... но вы 9X_.cs-file столкнетесь с повреждением данных при отправке 9X_csharp материалов по SMTP (если вам это нужно). Я 9X_.net-framework-3.5 изменил что-то еще, что поможет правильно 9X_.net-framework-3.5 отправлять байт за байтом: '

using System; using System.IO; private static byte[] ReadFully(string input) { FileStream sourceFile = new FileStream(input, FileMode.Open); //Open streamer BinaryReader binReader = new BinaryReader(sourceFile); byte[] output = new byte[sourceFile.Length]; //create byte array of size file for (long i = 0; i < sourceFile.Length; i++) output[i] = binReader.ReadByte(); //read until done sourceFile.Close(); //dispose streamer binReader.Close(); //dispose reader return output; }' 

4
2

  • Немного устарел, но я почувствовал, что об этом стоит упомянуть - реализация @NothinRandom обеспечивает работу со строками, а не с потоками. Однако в этом случае, вер ...

Ответ #11

Ответ на вопрос: Создание байтового массива из потока

public static byte[] ToByteArray(Stream stream) { if (stream is MemoryStream) { return ((MemoryStream)stream).ToArray(); } else { byte[] buffer = new byte[16 * 1024]; using (MemoryStream ms = new MemoryStream()) { int read; while ((read = stream.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); } return ms.ToArray(); } } } 
9X_.cs-file
4
1

  • Вы просто скопировали код из ответов №1 и №3, не добавив ничего цен ...

Ответ #12

Ответ на вопрос: Создание байтового массива из потока

Создайте вспомогательный класс и ссылайтесь 9X_visual-c# на него везде, где хотите его использовать.

public static class StreamHelpers { public static byte[] ReadFully(this Stream input) { using (MemoryStream ms = new MemoryStream()) { input.CopyTo(ms); return ms.ToArray(); } } } 

4
0

Ответ #13

Ответ на вопрос: Создание байтового массива из потока

В пространстве имен RestSharp.Extensions 9X_c#-language есть метод ReadAsBytes. Внутри этого метода 9X_.cs-file используется MemoryStream, и есть тот же 9X_inputstream код, что и в некоторых примерах на этой 9X_inputstream странице, но когда вы используете RestSharp, это 9X_.net-framework-3.5 самый простой способ.

using RestSharp.Extensions; var byteArray = inputStream.ReadAsBytes(); 

4
0

Ответ #14

Ответ на вопрос: Создание байтового массива из потока

Если поток поддерживает свойство Length, байтовый 9X_visual-c# массив может быть создан непосредственно 9X_framework3.5 из него. Преимущество состоит в том, что 9X_inputstream MemoryStream.ToArray создает массив дважды, плюс, возможно, несколько 9X_.net-framework-3.5 неиспользуемых дополнительных байтов в буфере. Это 9X_c-sharp решение выделяет точный необходимый массив. Если 9X_c#-language поток не поддерживает свойство Length, он 9X_inputstream вызовет исключение NotSupportedException.

Также стоит отметить, что 9X_.net-framework-3.5 массивы не могут быть больше int.MaxValue.

public static async Task ToArrayAsync(this Stream stream) { if (stream.Length > int.MaxValue) { throw new ArgumentOutOfRangeException("Cannot convert stream larger than max value of signed integer (2 147 483 647) to array"); } var array = new byte[stream.Length]; await stream.ReadAsync(array, 0, (int)stream.Length); return array; } 

4
0

Ответ #15

Ответ на вопрос: Создание байтового массива из потока

Это функция, которую я использую, протестировал 9X_.net-framework-3.5 и хорошо отработал. имейте в виду, что input 9X_c#-language не должен быть нулевым, а input.position 9X_.cs-file должен быть сброшен на 0 перед чтением, иначе 9X_c# цикл чтения прервется, и ничто не будет 9X_c#.net считываться для преобразования в массив.

 public static byte[] StreamToByteArray(Stream input) { if (input == null) return null; byte[] buffer = new byte[16 * 1024]; input.Position = 0; using (MemoryStream ms = new MemoryStream()) { int read; while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); } byte[] temp = ms.ToArray(); return temp; } } 

3
0

Ответ #16

Ответ на вопрос: Создание байтового массива из потока

Вы можете использовать этот метод расширения.

public static class StreamExtensions { public static byte[] ToByteArray(this Stream stream) { var bytes = new List(); int b; while ((b = stream.ReadByte()) != -1) bytes.Add((byte)b); return bytes.ToArray(); } } 

9X_inputstream

2
0

Ответ #17

Ответ на вопрос: Создание байтового массива из потока

Поскольку современной (т.е. асинхронной) версии 9X_c-sharp этого ответа нет, я использую для этой цели 9X_c-sharp метод расширения:

public static async Task ReadAsByteArrayAsync(this Stream source) { // Optimization if (source is MemoryStream memorySource) return memorySource.ToArray(); using var memoryStream = new MemoryStream(); await source.CopyToAsync(memoryStream); return memoryStream.ToArray(); } 

Оптимизация основана на 9X_c#-language том факте, что source code for ToArray вызывает некоторые внутренние 9X_inputstream методы.

1
0