it-swarm.com.de

Wie erstelle ich einen Stream aus einem String?

Ich muss einen Komponententest für eine Methode schreiben, die einen Stream aus einer Textdatei aufnimmt. Ich würde gerne so etwas machen:

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

Vergiss nicht zu benutzen mit:

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

Über das StreamWriter wird nicht verfügt. StreamWriter ist nur ein Wrapper um den Basisstream und verwendet keine Ressourcen, die entsorgt werden müssen. Die Methode Dispose schließt das zugrunde liegende Stream, in das StreamWriter schreibt. In diesem Fall ist dies das MemoryStream, das wir zurückgeben möchten.

In .NET 4.5 gibt es jetzt eine Überladung für StreamWriter, die den zugrunde liegenden Stream offen hält, nachdem der Writer gelöscht wurde. Dieser Code macht jedoch dasselbe und funktioniert auch mit anderen Versionen von .NET.

Siehe Gibt es eine Möglichkeit, einen StreamWriter zu schließen, ohne seinen BaseStream zu schließen?

882

Eine andere Lösung:

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

Fügen Sie dies zu einer statischen String-Utility-Klasse hinzu:

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

Dies fügt eine Erweiterungsfunktion hinzu, so dass Sie einfach:

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

Verwenden Sie die Klasse MemoryStream, und rufen Sie Encoding.GetBytes auf, um Ihre Zeichenfolge zuerst in ein Array von Bytes umzuwandeln.

Benötigen Sie anschließend ein TextReader im Stream? In diesem Fall können Sie direkt StringReader eingeben und die Schritte MemoryStream und Encoding umgehen.

23
Tim Robinson

Ich habe eine Mischung aus Antworten wie diese verwendet:

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

Und dann benutze ich es so:

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

Bitte schön:

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

Wir verwenden die unten aufgeführten Erweiterungsmethoden. Ich denke, Sie sollten den Entwickler dazu bringen, eine Entscheidung über die Kodierung zu treffen, damit weniger Magie involviert ist.

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

Modernisierte und leicht modifizierte Version der Erweiterungsmethoden für 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));

Änderung wie in @ Palecs Kommentar zu @Shaun Bowes Antwort vorgeschlagen.

8
Nick N.

Ich denke, Sie können von der Verwendung eines MemoryStream profitieren. Sie können es mit den Zeichenfolgenbytes füllen, die Sie mithilfe der GetBytes -Methode der Encoding-Klasse erhalten.

8
Konamiman

Wenn Sie die Kodierung ändern müssen, stimme ich für die Lösung von @ ShaunBowe . Bei jeder Antwort wird jedoch mindestens einmal die gesamte Zeichenfolge in den Speicher kopiert. Die Antworten mit ToCharArray + BlockCopy machen das zweimal.

Wenn dies von Bedeutung ist, finden Sie hier einen einfachen Stream Wrapper für die unformatierte UTF-16-Zeichenfolge. Bei Verwendung mit StreamReader wählen Sie Encoding.Unicode aus:

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

Und hier ist eine vollständigere Lösung mit den erforderlichen gebundenen Prüfungen (abgeleitet von MemoryStream, so dass es auch ToArray und WriteTo Methoden gibt).

1
György Kőszeg