web-dev-qa-db-fra.com

Ecrire StringBuilder pour diffuser

Quelle est la meilleure méthode pour écrire un StringBuilder dans un System.IO.Stream?

Je suis en train de faire:

StringBuilder message = new StringBuilder("All your base");
message.Append(" are belong to us");

System.IO.MemoryStream stream = new System.IO.MemoryStream();
System.Text.ASCIIEncoding encoding = new ASCIIEncoding();
stream.Write(encoder.GetBytes(message.ToString()), 0, message.Length);
49
Andy Joiner

N'utilisez pas de StringBuilder, si vous écrivez dans un flux, faites simplement cela avec un StreamWriter :

using (var memoryStream = new MemoryStream())
using (var writer = new StreamWriter(memoryStream ))
{
    // Various for loops etc as necessary that will ultimately do this:
    writer.Write(...);
}
76
Neil Barnwell

C'est la meilleure méthode. D’autres sage perdent le StringBuilder et utilisent quelque chose comme suit:

using (MemoryStream ms = new MemoryStream())
{
    using (StreamWriter sw = new StreamWriter(ms, Encoding.Unicode))
    {
        sw.WriteLine("dirty world.");
    }
    //do somthing with ms
}
14
particle

En fonction de votre cas d'utilisation, il peut également être judicieux de commencer par un StringWriter:

StringBuilder sb = null;

// StringWriter - a TextWriter backed by a StringBuilder
using (var writer = new StringWriter())
{
    writer.WriteLine("Blah");
    . . .
    sb = writer.GetStringBuilder(); // Get the backing StringBuilder out
}

// Do whatever you want with the StringBuilder
5
Chris Moschini

Ce sera peut-être utile.

var sb= new StringBuilder("All your money");
sb.Append(" are belong to us, dude.");
var myString = sb.ToString();
var myByteArray = System.Text.Encoding.UTF8.GetBytes(myString);
var ms = new MemoryStream(myByteArray);
// Do what you need with MemoryStream

Si vous souhaitez utiliser quelque chose comme un StringBuilder, car il est plus facile de le transmettre et de le manipuler, vous pouvez utiliser quelque chose comme le substitut StringBuilder suivant que j'ai créé.

La différence la plus importante est qu’elle autorise l’accès aux données internes sans avoir à les assembler au préalable dans une chaîne ou un ByteArray. Cela signifie que vous n'êtes pas obligé de doubler les besoins en mémoire et de risquer d'allouer une partie de mémoire contiguë qui s'adapte à l'ensemble de votre objet.

REMARQUE: Je suis sûr qu'il existe de meilleures options que d'utiliser une List<string>() en interne, mais cela était simple et s'est avéré suffisant pour mes besoins.

public class StringBuilderEx
{
    List<string> data = new List<string>();
    public void Append(string input)
    {
        data.Add(input);
    }
    public void AppendLine(string input)
    {
        data.Add(input + "\n");
    }
    public void AppendLine()
    {
        data.Add("\n");
    }

    /// <summary>
    /// Copies all data to a String.
    /// Warning: Will fail with an OutOfMemoryException if the data is too
    /// large to fit into a single contiguous string.
    /// </summary>
    public override string ToString()
    {
        return String.Join("", data);
    }

    /// <summary>
    /// Process Each section of the data in place.   This avoids the
    /// memory pressure of exporting everything to another contiguous
    /// block of memory before processing.
    /// </summary>
    public void ForEach(Action<string> processData)
    {
        foreach (string item in data)
            processData(item);
    }
}

Vous pouvez maintenant vider l'intégralité du contenu dans un fichier à l'aide du code suivant.

var stringData = new StringBuilderEx();
stringData.Append("Add lots of data");

using (StreamWriter file = new System.IO.StreamWriter(localFilename))
{
    stringData.ForEach((data) =>
    {
        file.Write(data);
    });
}
0
AnthonyVO