Как преобразовать stream в байт в C #?

Есть ли простой способ или метод для преобразования Stream в byte[] в C #?

Вызовите следующую функцию, например

 byte[] m_Bytes = StreamHelper.ReadToEnd (mystream); 

Функция:

 public static byte[] ReadToEnd(System.IO.Stream stream) { long originalPosition = 0; if(stream.CanSeek) { originalPosition = stream.Position; stream.Position = 0; } try { byte[] readBuffer = new byte[4096]; int totalBytesRead = 0; int bytesRead; while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0) { totalBytesRead += bytesRead; if (totalBytesRead == readBuffer.Length) { int nextByte = stream.ReadByte(); if (nextByte != -1) { byte[] temp = new byte[readBuffer.Length * 2]; Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length); Buffer.SetByte(temp, totalBytesRead, (byte)nextByte); readBuffer = temp; totalBytesRead++; } } } byte[] buffer = readBuffer; if (readBuffer.Length != totalBytesRead) { buffer = new byte[totalBytesRead]; Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead); } return buffer; } finally { if(stream.CanSeek) { stream.Position = originalPosition; } } } 

Самое короткое решение, которое я знаю:

 using(var memoryStream = new MemoryStream()) { sourceStream.CopyTo(memoryStream); return memoryStream.ToArray(); } 

В .NET Framework 4 и более поздних версиях class Stream имеет встроенный метод CopyTo который вы можете использовать.

Для более ранних версий структуры удобная вспомогательная функция:

 public static void CopyStream(Stream input, Stream output) { byte[] b = new byte[32768]; int r; while ((r = input.Read(b, 0, b.Length)) > 0) output.Write(b, 0, r); } 

Затем используйте один из вышеуказанных методов для копирования в MemoryStream и вызовите GetBuffer :

 var file = new FileStream("c:\\foo.txt", FileMode.Open); var mem = new MemoryStream(); // If using .NET 4 or later: file.CopyTo(mem); // Otherwise: CopyStream(file, mem); // getting the internal buffer (no additional copying) byte[] buffer = mem.GetBuffer(); long length = mem.Length; // the actual length of the data // (the array may be longer) // if you need the array to be exactly as long as the data byte[] truncated = mem.ToArray(); // makes another copy 

Изменить: первоначально я предложил использовать ответ Джейсона для Stream который поддерживает свойство Length . Но у него был недостаток, потому что предполагалось, что Stream вернет все его содержимое в одном Read , что не обязательно верно (не для Socket , например.) Я не знаю, есть ли пример реализации Stream в BCL, который поддерживает Length но может возвращать данные в более короткие куски, чем вы запрашиваете, но поскольку кто-то может наследовать Stream это может быть легко.

В большинстве случаев, вероятно, проще использовать вышеупомянутое общее решение, но предположим, что вы хотели бы читать непосредственно в массив, который является bigEnough .

 byte[] b = new byte[bigEnough]; int r, offset; while ((r = input.Read(b, offset, b.Length - offset)) > 0) offset += r; 

То есть, повторно вызывайте « Read и перемещайте позицию, в которой вы будете хранить данные.

  byte[] buf; // byte array Stream stream=Page.Request.InputStream; //initialise new stream buf = new byte[stream.Length]; //declare arraysize stream.Read(buf, 0, buf.Length); // read from stream to byte array 

Я использую этот class расширения:

 public static class StreamExtensions { public static byte[] ReadAllBytes(this Stream instream) { if (instream is MemoryStream) return ((MemoryStream) instream).ToArray(); using (var memoryStream = new MemoryStream()) { instream.CopyTo(memoryStream); return memoryStream.ToArray(); } } } 

Просто скопируйте class в свое решение, и вы можете использовать его для каждого streamа:

 byte[] bytes = myStream.ReadAllBytes() 

Отлично работает для всех моих streamов и сохраняет много кода! Конечно, вы можете изменить этот метод, чтобы использовать некоторые из других подходов здесь для повышения производительности, если это необходимо, но мне нравится держать его простым.

 Byte[] Content = new BinaryReader(file.InputStream).ReadBytes(file.ContentLength); 

Хорошо, может быть, я что-то пропустил, но так я это делаю:

 public static Byte[] ToByteArray(this Stream stream) { Int32 length = stream.Length > Int32.MaxValue ? Int32.MaxValue : Convert.ToInt32(stream.Length); Byte[] buffer = new Byte[length]; stream.Read(buffer, 0, length); return buffer; } 

Быстрая и грязная техника:

  static byte[] StreamToByteArray(Stream inputStream) { if (!inputStream.CanRead) { throw new ArgumentException(); } // This is optional if (inputStream.CanSeek) { inputStream.Seek(0, SeekOrigin.Begin); } byte[] output = new byte[inputStream.Length]; int bytesRead = inputStream.Read(output, 0, output.Length); Debug.Assert(bytesRead == output.Length, "Bytes read from stream matches stream length"); return output; } 

Контрольная работа:

  static void Main(string[] args) { byte[] data; string path = @"C:\Windows\System32\notepad.exe"; using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read)) { data = StreamToByteArray(fs); } Debug.Assert(data.Length > 0); Debug.Assert(new FileInfo(path).Length == data.Length); } 

Я бы спросил, почему вы хотите прочитать stream в байт [], если вы хотите скопировать содержимое streamа, могу ли я предложить использовать MemoryStream и записать stream ввода в stream памяти.

если вы отправляете файл с мобильного устройства или другого

  byte[] fileData = null; using (var binaryReader = new BinaryReader(Request.Files[0].InputStream)) { fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength); } 
 Stream s; int len = (int)s.Length; byte[] b = new byte[len]; int pos = 0; while((r = s.Read(b, pos, len - pos)) > 0) { pos += r; } 

Требуется несколько более сложное решение: s.Length превышает Int32.MaxValue . Но если вам нужно прочитать stream, который в большой памяти, вы можете подумать о другом подходе к вашей проблеме.

Изменить: если ваш stream не поддерживает свойство Length , измените его с помощью обходного метода Earwicker.

 public static class StreamExtensions { // Credit to Earwicker public static void CopyStream(this Stream input, Stream output) { byte[] b = new byte[32768]; int r; while ((r = input.Read(b, 0, b.Length)) > 0) { output.Write(b, 0, r); } } } [...] Stream s; MemoryStream ms = new MemoryStream(); s.CopyStream(ms); byte[] b = ms.GetBuffer(); 

Вы также можете попробовать просто прочитать по частям за раз и увеличить возвращаемый массив байтов:

 public byte[] StreamToByteArray(string fileName) { byte[] total_stream = new byte[0]; using (Stream input = File.Open(fileName, FileMode.Open, FileAccess.Read)) { byte[] stream_array = new byte[0]; // Setup whatever read size you want (small here for testing) byte[] buffer = new byte[32];// * 1024]; int read = 0; while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { stream_array = new byte[total_stream.Length + read]; total_stream.CopyTo(stream_array, 0); Array.Copy(buffer, 0, stream_array, total_stream.Length, read); total_stream = stream_array; } } return total_stream; } 

«BigEnough» массив немного растянут. Разумеется, буфер должен быть «большим», но правильный дизайн приложения должен включать транзакции и разделители. В этой конфигурации каждая транзакция будет иметь заданную длину, поэтому ваш массив будет ожидать определенное количество байтов и вставить его в буфер с правильным размером. Разделители гарантируют целостность транзакции и будут поставляться в рамках каждой транзакции. Чтобы сделать ваше приложение еще лучше, вы можете использовать 2 канала (2 гнезда). Можно было бы связывать транзакции с фиксированной длиной управления, которые будут включать информацию о размере и порядковом номере транзакции данных, которая будет передана с использованием канала данных. Приемник подтвердил создание буфера, и только тогда данные будут отправлены. Если у вас нет контроля над отправителем streamа, вам нужен multidimensional array в качестве буфера. Компонентные массивы будут достаточно малы, чтобы быть управляемыми и достаточно большими, чтобы быть практичными на основе вашей оценки ожидаемых данных. Логика процесса будет искать известные начальные разделители и затем заканчивать разделитель в последующих массивах элементов. После того, как будет найден конечный разделитель, будет создан новый буфер для хранения соответствующих данных между разделителями и начальным буфером, чтобы можно было удалить данные.

Что касается кода для преобразования streamа в массив байтов, то ниже.

 Stream s = yourStream; int streamEnd = Convert.ToInt32(s.Length); byte[] buffer = new byte[streamEnd]; s.Read(buffer, 0, streamEnd); 
  • Печать входного streamа Java из процесса
  • Различные способы загрузки файла в качестве InputStream
  • Самый эффективный способ создания InputStream из OutputStream
  • Когда произойдет EOFException в streamах JAVA
  • Как проверить, нажал ли пользователь клавишу?
  • Ввод ввода с джойстика с помощью C # .NET
  • Как преобразовать символ в эквивалентное значение System.Windows.Input.Key Enum?
  • Как преобразовать InputStream в виртуальный файл
  • Как клонировать InputStream?
  • CSS-вход с шириной: 100% выходит за пределы родительской привязки
  • Interesting Posts

    Невозможно сопоставить определенный порт и путь с файлами hosts

    Содержимое HTML соответствует UIWebview без масштабирования

    Tricky trernary operator в Java – автобоксинг

    C # ждать, пока пользователь завершит ввод текстового поля

    Причина использования ivars против свойств в объекте c

    Как написать «Html.BeginForm» в Razor

    Очистите диск по ошибке с помощью diskpart. Возможно ли восстановить данные, хранящиеся в конкретном разделе?

    Есть ли способ программно прокрутить представление прокрутки к определенному тексту редактирования?

    В чем разница между SessionState и ViewState?

    «Смотреть» вывод команды до тех пор, пока не будет наблюдаться определенная строка, а затем выйдите

    MediaWiki: ограничение доступа к просмотру / редактированию

    Как остановить запуск программ из моего браузера?

    Есть ли программа сжатия или архивирования для Windows, которая также выполняет дедупликацию?

    Функция определяется специальными случаями в GHCi

    Как создать пользователя SSH, у которого есть разрешение на доступ к определенным папкам в Ubuntu?

    Давайте будем гением компьютера.