2 votes

comment mettre en mémoire tampon un flux d'entrée jusqu'à ce qu'il soit complet

Je suis en train d'implémenter un service wcf qui accepte les flux d'images. cependant, j'obtiens actuellement une exception lorsque je l'exécute. car il essaie d'obtenir la longueur du flux avant que le flux ne soit complet. donc, ce que j'aimerais faire, c'est mettre en mémoire tampon le flux jusqu'à ce qu'il soit complet. cependant, je ne trouve aucun exemple de la façon de le faire....

Quelqu'un peut-il m'aider ?

mon code jusqu'à présent :

    public String uploadUserImage(Stream stream)
    {
          Stream fs = stream;

          BinaryReader br = new BinaryReader(fs);

          Byte[] bytes = br.ReadBytes((Int32)fs.Length);// this causes exception

          File.WriteAllBytes(filepath, bytes);
    }

9voto

Jon Skeet Points 692016

Plutôt que d'essayer de récupérer la longueur, vous devriez lire le flux jusqu'à ce qu'il vous dise qu'il est "terminé". Dans .NET 4, c'est très facile :

// Assuming we *really* want to read it into memory first...
MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
memoryStream.Position = 0;
File.WriteAllBytes(filepath, memoryStream);

Dans .NET 3.5 il n'y a pas de CopyTo mais vous pouvez écrire quelque chose de similaire vous-même :

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

Cependant, maintenant que nous avons quelque chose pour copier un flux, pourquoi s'embêter à tout lire en mémoire d'abord ? Écrivons-le directement dans un fichier :

using (FileStream output = File.OpenWrite(filepath))
{
    CopyStream(stream, output); // Or stream.CopyTo(output);
}

1voto

jp2code Points 8461

Je ne suis pas sûr de ce que vous renvoyez (ou ne renvoyez pas), mais quelque chose comme ceci pourrait fonctionner pour vous :

public String uploadUserImage(Stream stream) {
  const int KB = 1024;
  Byte[] bytes = new Byte[KB];
  StringBuilder sb = new StringBuilder();
  using (BinaryReader br = new BinaryReader(stream)) {
    int len;
    do {
      len = br.Read(bytes, 0, KB);
      string readData = Encoding.UTF8.GetString(bytes);
      sb.Append(readData);
    } while (len == KB);
  }
  //File.WriteAllBytes(filepath, bytes);
  return sb.ToString();
}

Une chaîne peut contenir jusqu'à 2 Go, je crois.

0voto

Hugh Jones Points 1444

Essayez ceci :

    using (StreamWriter sw = File.CreateText(filepath))
    {
        stream.CopyTo(sw);
        sw.Close();
    }

-1voto

Ma Dude Points 307

La réponse de Jon Skeets concernant l'utilisation d'un Buffer Read dans les versions .Net 3.5 et inférieures est en fait incorrecte.

Le tampon n'est pas effacé entre les lectures, ce qui peut entraîner des problèmes pour toute lecture qui renvoie moins de 8192, par exemple si la deuxième lecture lit 192 octets, les 8000 derniers octets de la première lecture seront TOUJOURS dans le tampon qui sera alors renvoyé au flux.

Dans mon code ci-dessous, vous lui fournissez un Stream et il retournera un tableau IEnumerable.
En utilisant ceci, vous pouvez for-each it et Write vers un MemoryStream et ensuite utiliser .GetBuffer() pour obtenir un byte[] compilé et fusionné.

private IEnumerable<byte[]> ReadFullStream(Stream stream) {
   while(true) {
        byte[] buffer = new byte[8192];//since this is created every loop, its buffer is cleared
        int bytesRead = stream.Read(buffer, 0, buffer.Length);//read up to 8192 bytes into buffer
        if (bytesRead == 0) {//if we read nothing, stream is finished
            break;
        }
        if(bytesRead < buffer.Length) {//if we read LESS than 8192 bytes, resize the buffer to essentially remove everything after what was read, otherwise you will have nullbytes/0x00bytes at the end of your buffer
            Array.Resize(ref buffer, bytesRead);
        }
        yield return buffer;//yield return the buffer data
    }//loop here until we reach a read == 0 (end of stream)
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X