Pergunta

Esta questão já tem uma resposta aqui:

Existe uma maneira simples ou método para converter um Stream em um byte[] em C #?

Foi útil?

Solução

Chamada próxima função como

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

Função:

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; 
            }
        }
    }

Outras dicas

A solução mais curta que eu sei:

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

No .NET Framework 4 e, mais tarde, a classe Stream tem um built-in método CopyTo que você pode usar.

Para versões anteriores do quadro, a função auxiliar útil para ter é:

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);
}

Em seguida, use um dos métodos acima para copiar para um MemoryStream e chamada GetBuffer nele:

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

Editar: originalmente eu sugeriu o uso de resposta de Jason para uma Stream que suporta a propriedade Length. Mas tinha uma falha, porque ele assumiu que o Stream retornaria todo o seu conteúdo em um único Read, que não é necessariamente verdade (não para um Socket, por exemplo.) Eu não sei se há um exemplo de uma implementação Stream na BCL que faz suporte Length mas pode retornar os dados em pedaços mais curtos do que você pedir, mas como alguém pode herdar Stream este poderia facilmente ser o caso.

É provavelmente mais simples para a maioria dos casos de usar a acima solução geral, mas supondo que você queria ler diretamente em uma matriz que é bigEnough:

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

Isto é, repetidamente chamar Read e mover a posição que você estará armazenando os dados em.

    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

Eu uso essa classe de extensão:

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();
        }
    }
}
copiar

Apenas a classe para a sua solução e você pode usá-lo em cada stream:

byte[] bytes = myStream.ReadAllBytes()

Funciona muito bem para todas as minhas correntes e salva um monte de código! Claro que você pode modificar este método a utilizar algumas das outras abordagens aqui para melhorar o desempenho, se necessário, mas eu gosto de mantê-lo simples.

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

Ok, talvez eu estou faltando alguma coisa aqui, mas esta é a maneira que eu fazê-lo:

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;
}

Se você postar um arquivo do dispositivo móvel ou outra

    byte[] fileData = null;
    using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
    {
        fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
    }

técnica rápida e suja:

    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;
    }

Test:

    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); 
    }

Gostaria de pedir, por que você quer ler um fluxo em um byte [], se você está desejando para copiar o conteúdo de um riacho, pode eu sugiro usar MemoryStream e escrever o seu fluxo de entrada em um fluxo de memória.

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;
}

Uma solução ligeiramente mais complicado é necesary é s.Length excede Int32.MaxValue. Mas se você precisa ler um fluxo tão grande na memória, você pode querer pensar em uma abordagem diferente para o seu problema.

Edit: Se o seu fluxo não suporta a propriedade Length, modificar usando de Earwicker solução alternativa .

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();

Você também pode tentar ler apenas em partes de cada vez e expandir a matriz de bytes a serem devolvidos:

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;
}

array "bigEnough" é um pouco de um trecho. Claro, as necessidades de buffer para ser "grande ebough", mas bom design de um aplicativo deve incluir transações e delimitadores. Nesta configuração cada operação teria um comprimento pré-definido, assim, a sua matriz iria antecipar certo número de bytes e inseri-lo em tampão de tamanho correcto. Delimitadores seria garantir a integridade da transação e será fornecido dentro de cada transação. Para tornar a sua aplicação ainda melhor, você poderia usar 2 canais (2 soquetes). Seria de comunicar operações de mensagens de controlo de comprimento fixo que incluem informações sobre o tamanho e número de sequência de transacção de dados a serem transferidas usando o canal de dados. Receptor reconheceria criação tampão e só então os dados seriam enviados. Se você não tem controle sobre o córrego remetente do que você precisa matriz multidimensional como um buffer. matrizes de componentes seria pequeno o suficiente para ser bastante gerenciável e grande para ser prático baseado em sua estimativa de dados esperados. lógica do processo procuraria delimitadores de início conhecidos e delimitador, em seguida, terminando em matrizes de elementos posteriores. Uma vez terminando delimitador for encontrada, novo buffer seria criado para armazenar dados relevantes entre delimitadores e tampão inicial teria de ser reestruturado para permitir dispor de dados.

Na medida em que um código de corrente convertido em matriz de bytes é um abaixo.

Stream s = yourStream;
int streamEnd = Convert.ToInt32(s.Length);
byte[] buffer = new byte[streamEnd];
s.Read(buffer, 0, streamEnd);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top