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

Каков предпочтительный метод создания массива 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