web-dev-qa-db-fra.com

Comment obtenir un MemoryStream à partir d'un flux dans .NET?

J'ai la méthode constructeur suivante qui ouvre un MemoryStream à partir d'un chemin de fichier:

MemoryStream _ms;

public MyClass(string filePath)
{
    byte[] docBytes = File.ReadAllBytes(filePath);
    _ms = new MemoryStream();
    _ms.Write(docBytes, 0, docBytes.Length);
}

Je dois changer cela pour accepter un Stream au lieu d'un chemin de fichier. Quel est le moyen le plus simple/le plus efficace pour obtenir un MemoryStream à partir de l'objet Stream?

60
fearofawhackplanet

Si vous modifiez votre classe pour accepter un Stream au lieu d'un nom de fichier, ne vous embêtez pas à convertir en MemoryStream. Laissez le flux sous-jacent gérer les opérations:

public class MyClass
{ 
    Stream _s;

    public MyClass(Stream s) { _s = s; }
}

Mais si vous avez vraiment besoin d'un MemoryStream pour les opérations internes, vous devrez copier les données du Stream source dans le MemoryStream:

public MyClass(Stream stream)
{
    _ms = new MemoryStream();
    CopyStream(stream, _ms);
}

// Merged From linked CopyStream below and Jon Skeet's ReadFully example
public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[16*1024];
    int read;
    while((read = input.Read (buffer, 0, buffer.Length)) > 0)
    {
        output.Write (buffer, 0, read);
    }
}
28
Justin Niessner

Dans .NET 4, vous pouvez utiliser Stream.CopyTo pour copier un flux, au lieu des méthodes de brassage maison répertoriées dans les autres réponses.

MemoryStream _ms;

public MyClass(Stream sourceStream)

    _ms = new MemoryStream();
    sourceStream.CopyTo(_ms);
}
181
Phil Devaney

Utilisez ceci:

var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);

Cela convertira Stream en MemoryStream.

42
user3608207

Vous devrez lire toutes les données de l'objet Stream dans un byte[] buffer puis passez-le dans MemoryStream via son constructeur. Il peut être préférable d'être plus précis sur le type d'objet de flux que vous utilisez. Stream est très générique et peut ne pas implémenter l'attribut Length, ce qui est plutôt utile lors de la lecture de données.

Voici du code pour vous:

public MyClass(Stream inputStream) {
    byte[] inputBuffer = new byte[inputStream.Length];
    inputStream.Read(inputBuffer, 0, inputBuffer.Length);

    _ms = new MemoryStream(inputBuffer);
}

Si l'objet Stream n'implémente pas l'attribut Length, vous devrez implémenter quelque chose comme ceci:

public MyClass(Stream inputStream) {
    MemoryStream outputStream = new MemoryStream();

    byte[] inputBuffer = new byte[65535];
    int readAmount;
    while((readAmount = inputStream.Read(inputBuffer, 0, inputBuffer.Length)) > 0)
        outputStream.Write(inputBuffer, 0, readAmount);

    _ms = outputStream;
}
3
rakuo15

J'utilise cette combinaison de méthodes d'extension:

    public static Stream Copy(this Stream source)
    {
        if (source == null)
            return null;

        long originalPosition = -1;

        if (source.CanSeek)
            originalPosition = source.Position;

        MemoryStream ms = new MemoryStream();

        try
        {
            Copy(source, ms);

            if (originalPosition > -1)
                ms.Seek(originalPosition, SeekOrigin.Begin);
            else
                ms.Seek(0, SeekOrigin.Begin);

            return ms;
        }
        catch
        {
            ms.Dispose();
            throw;
        }
    }

    public static void Copy(this Stream source, Stream target)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        if (target == null)
            throw new ArgumentNullException("target");

        long originalSourcePosition = -1;
        int count = 0;
        byte[] buffer = new byte[0x1000];

        if (source.CanSeek)
        {
            originalSourcePosition = source.Position;
            source.Seek(0, SeekOrigin.Begin);
        }

        while ((count = source.Read(buffer, 0, buffer.Length)) > 0)
            target.Write(buffer, 0, count);

        if (originalSourcePosition > -1)
        {
            source.Seek(originalSourcePosition, SeekOrigin.Begin);
        }
    }
2
Toby

Comment copier le contenu d'un flux dans un autre?

regarde ça. accepter un flux et copier dans la mémoire. vous ne devez pas utiliser .Length pour juste Stream car il n'est pas nécessairement implémenté dans chaque Stream concret.

2
Andrey
public static void Do(Stream in)
{
    _ms = new MemoryStream();
    byte[] buffer = new byte[65536];
    while ((int read = input.Read(buffer, 0, buffer.Length))>=0)
        _ms.Write (buffer, 0, read);
}
1
Mau
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
    fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}
0
Savas Adar

Vous pouvez simplement faire:

var ms = new MemoryStream(File.ReadAllBytes(filePath));

La position du flux est 0 et prête à l'emploi.

0
Rebecca