Question

    

Cette question a déjà une réponse ici:

         

Y at-il un moyen simple ou une méthode pour convertir un Stream en byte[] en C #?

Était-ce utile?

La solution

Appel fonction suivante comme

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

Fonction:

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

Autres conseils

La solution la plus courte, je sais:

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

Dans .NET Framework 4 et plus tard, la classe Stream a une méthode de CopyTo intégré que vous pouvez utiliser.

Pour les versions antérieures du cadre, la fonction d'aide pratique d'avoir est:

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

Ensuite, utilisez l'une des méthodes ci-dessus pour copier un MemoryStream et appelez GetBuffer sur elle:

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

Modifier à l'origine je suggéré d'utiliser la réponse de Jason pour un Stream qui prend en charge la propriété Length. Mais il y avait une faille parce qu'elle suppose que le Stream retournerait tout son contenu dans un seul Read, ce qui est pas nécessairement vrai (pas un Socket, par exemple.) Je ne sais pas s'il est un exemple de mise en œuvre de Stream dans la BCL qui prend en charge Length mais peut renvoyer les données en morceaux plus courts que vous demandez, mais comme tout le monde peut hériter Stream cela pourrait facilement être le cas.

Il est probablement plus simple pour la plupart des cas d'utiliser la solution générale ci-dessus, mais vous ne supposant envie de lire directement dans un tableau qui est bigEnough:

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

C'est, appeler à plusieurs reprises Read et déplacer la position que vous entreposez les données à.

    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

J'utilise cette classe d'extension:

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

Il suffit de copier la classe à votre solution et vous pouvez l'utiliser sur tous les flux:

byte[] bytes = myStream.ReadAllBytes()

fonctionne très bien pour tous mes cours d'eau et permet d'économiser beaucoup de code! Bien sûr, vous pouvez modifier cette méthode pour utiliser certaines des autres approches ici pour améliorer les performances en cas de besoin, mais je tiens à le garder simple.

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

Ok, peut-être je manque quelque chose ici, mais c'est la façon dont je le fais:

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

si vous affichez un fichier à partir d'un appareil mobile ou autre

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

technique rapide et sale:

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

Je demanderais, pourquoi voulez-vous lire un flux dans un octet [], si vous êtes désireux de copier le contenu d'un flux, puis-je suggère d'utiliser MemoryStream et écrire votre flux d'entrée dans un flux de mémoire.

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

Une solution un peu plus complexe est necesary est s.Length dépasse Int32.MaxValue. Mais si vous avez besoin de lire un flux important dans la mémoire, vous voudrez peut-être penser à une approche différente de votre problème.

Edit: Si votre flux ne supporte pas la propriété Length, modifier à l'aide de Earwicker solution .

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

Vous pouvez également essayer de simplement lire dans les parties à la fois et l'élargissement du tableau d'octets retour:

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 » est un peu exagéré. Bien sûr, le tampon doit être « grand ebough » mais une bonne conception d'une application devrait inclure les transactions et délimiteurs. Dans cette configuration chaque transaction aurait une longueur prédéterminée ainsi votre tableau anticiperait certain nombre d'octets et l'insérer dans un tampon correctement dimensionné. Délimiteurs assureraient l'intégrité des transactions et seraient fournis dans chaque transaction. Pour votre application encore mieux, vous pouvez utiliser 2 canaux (2 prises). On pourrait communiquer les transactions de messages de contrôle de longueur fixe qui comprennent des informations sur la taille et le numéro de séquence de transaction de données à transférer en utilisant le canal de données. Récepteur reconnaîtrait la création de tampon et alors seulement serait envoyé des données. Si vous avez aucun contrôle sur l'expéditeur de flux que vous avez besoin tableau multidimensionnel comme un tampon. tableaux de composants seraient suffisamment petits pour être assez facile à gérer et grand pour être pratique en fonction de votre estimation des données attendues. la logique du processus chercherait délimiteurs de début connus et puis la fin delimiter dans des réseaux d'éléments ultérieurs. Une fois que délimiteur final se trouve, nouveau tampon sera créé pour stocker des données pertinentes entre délimiteurs et le tampon initial devrait être restructuré afin de permettre l'élimination des données.

En ce qui concerne un code à convertir en courant du tableau d'octets est une ci-dessous.

Stream s = yourStream;
int streamEnd = Convert.ToInt32(s.Length);
byte[] buffer = new byte[streamEnd];
s.Read(buffer, 0, streamEnd);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top