web-dev-qa-db-fra.com

Comment générer un flux à partir d'une chaîne?

J'ai besoin d'écrire un test unitaire pour une méthode prenant un flux qui provient d'un fichier texte. Je voudrais faire quelque chose comme ça:

Stream s = GenerateStreamFromString("a,b \n c,d");
691
Omu
public static Stream GenerateStreamFromString(string s)
{
    var stream = new MemoryStream();
    var writer = new StreamWriter(stream);
    writer.Write(s);
    writer.Flush();
    stream.Position = 0;
    return stream;
}

N'oubliez pas d'utiliser Using:

using (var stream = GenerateStreamFromString("a,b \n c,d"))
{
    // ... Do stuff to stream
}

À propos de la StreamWriter non éliminée. StreamWriter est simplement un wrapper autour du flux de base et n'utilise pas de ressources devant être éliminées. La méthode Dispose ferme le sous-jacent Stream auquel StreamWriter écrit. Dans ce cas, c’est la MemoryStream à renvoyer.

Dans .NET 4.5, il existe maintenant une surcharge pour StreamWriter qui maintient le flux sous-jacent ouvert après la suppression de l'enregistreur, mais ce code fait la même chose et fonctionne également avec d'autres versions de .NET.

Voir Est-il possible de fermer un StreamWriter sans fermer son BaseStream?

882
Cameron MacFarland

Une autre solution:

public static MemoryStream GenerateStreamFromString(string value)
{
    return new MemoryStream(Encoding.UTF8.GetBytes(value ?? ""));
}
659
joelnet

Ajoutez ceci à une classe d'utilitaire de chaîne statique:

public static Stream ToStream(this string str)
{
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(str);
    writer.Flush();
    stream.Position = 0;
    return stream;
}

Cela ajoute une fonction d’extension pour que vous puissiez simplement:

using (var stringStream = "My string".ToStream())
{
    // use stringStream
}
106
Josh G
public Stream GenerateStreamFromString(string s)
{
    return new MemoryStream(Encoding.UTF8.GetBytes(s));
}
38
Warlock

Utilisez la classe MemoryStream en appelant Encoding.GetBytes pour convertir votre chaîne en tableau d’octets.

Avez-vous besoin par la suite d'une TextReader sur le flux? Si tel est le cas, vous pouvez fournir directement une StringReader et contourner les étapes MemoryStream et Encoding.

23
Tim Robinson

J'ai utilisé un mélange de réponses comme ceci:

public static Stream ToStream(this string str, Encoding enc = null)
{
    enc = enc ?? Encoding.UTF8;
    return new MemoryStream(enc.GetBytes(str ?? ""));
}

Et puis je l'utilise comme ça:

String someStr="This is a Test";
Encoding enc = getEncodingFromSomeWhere();
using (Stream stream = someStr.ToStream(enc))
{
    // Do something with the stream....
}
15
Robocide

Voici:

private Stream GenerateStreamFromString(String p)
{
    Byte[] bytes = UTF8Encoding.GetBytes(p);
    MemoryStream strm = new MemoryStream();
    strm.Write(bytes, 0, bytes.Length);
    return strm;
}
9
cjk

Nous utilisons les méthodes d'extension listées ci-dessous. Je pense que vous devriez faire en sorte que le développeur prenne une décision concernant l'encodage, afin qu'il y ait moins de magie.

public static class StringExtensions {

    public static Stream ToStream(this string s) {
        return s.ToStream(Encoding.UTF8);
    }

    public static Stream ToStream(this string s, Encoding encoding) {
        return new MemoryStream(encoding.GetBytes(s ?? ""));
    }
}
9
Shaun Bowe

Version modernisée et légèrement modifiée des méthodes d'extension pour ToStream:

public static Stream ToStream(this string value) => ToStream(value, Encoding.UTF8);

public static Stream ToStream(this string value, Encoding encoding) 
                          => new MemoryStream(encoding.GetBytes(value ?? string.Empty));

Modification comme suggéré dans le commentaire de @ Palec sur la réponse de Shaun Bowe.

8
Nick N.

Je pense que vous pouvez tirer parti de l’utilisation de MemoryStream . Vous pouvez le remplir avec les octets de chaîne que vous obtenez en utilisant la méthode GetBytes de Classe de codage .

8
Konamiman

Si vous devez modifier l'encodage, je vote pour la solution de @ ShaunBowe . Mais chaque réponse ici copie la chaîne entière en mémoire au moins une fois. Les réponses avec la combinaison ToCharArray + BlockCopy le font deux fois.

Si cela compte, voici un simple wrapper Stream pour la chaîne brute UTF-16. Si utilisé avec un StreamReader sélectionnez Encoding.Unicode pour cela:

public class StringStream : Stream
{
    private readonly string str;

    public override bool CanRead => true;
    public override bool CanSeek => true;
    public override bool CanWrite => false;
    public override long Length => str.Length * 2;
    public override long Position { get; set; } // TODO: bounds check

    public StringStream(string s) => str = s ?? throw new ArgumentNullException(nameof(s));

    public override long Seek(long offset, SeekOrigin Origin)
    {
        switch (Origin)
        {
            case SeekOrigin.Begin:
                Position = offset;
                break;
            case SeekOrigin.Current:
                Position += offset;
                break;
            case SeekOrigin.End:
                Position = Length - offset;
                break;
        }

        return Position;
    }

    private byte this[int i] => (i & 1) == 0 ? (byte)(str[i / 2] & 0xFF) : (byte)(str[i / 2] >> 8);

    public override int Read(byte[] buffer, int offset, int count)
    {
        // TODO: bounds check
        var len = Math.Min(count, Length - Position);
        for (int i = 0; i < len; i++)
            buffer[offset++] = this[(int)(Position++)];
        return (int)len;
    }

    public override int ReadByte() => Position >= Length ? -1 : this[(int)Position++];
    public override void Flush() { }
    public override void SetLength(long value) => throw new NotSupportedException();
    public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
    public override string ToString() => str; // ;)     
}

Et ici est une solution plus complète avec les contrôles liés nécessaires (dérivée de MemoryStream et donc des méthodes ToArray et WriteTo.).

1
György Kőszeg