web-dev-qa-db-ja.com

文字列からストリームを生成する方法

テキストファイルから来るストリームを受け取るメソッドのためのユニットテストを書く必要があります。私はこのようなことをしたいのですが。

Stream s = GenerateStreamFromString("a,b \n c,d");
669
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;
}

使用することを忘れないでください:

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

StreamWriterが破棄されていないことについて。 StreamWriterは、基本ストリームの単なるラッパーであり、破棄する必要のあるリソースを一切使用しません。 Disposeメソッドは、Streamが書き込んでいる基礎となるStreamWriterをクローズします。この場合、それが戻りたいMemoryStreamです。

.NET 4.5では、ライターが破棄された後も基になるストリームを開いたままにするStreamWriterのオーバーロードがありますが、このコードは同じことを行い、他のバージョンの.NETでも機能します。

参照 BaseStreamを閉じずにStreamWriterを閉じる方法はありますか。

854

別の解決策:

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

これを静的文字列ユーティリティクラスに追加します。

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

これは拡張機能を追加するので、単純に次のことができます。

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

文字列を最初にバイトの配列に変換するには、Encoding.GetBytesを呼び出してMemoryStreamクラスを使用します。

その後ストリームにTextReaderが必要ですか。もしそうなら、あなたは直接StringReaderを供給し、MemoryStreamEncodingステップを迂回することができます。

22
Tim Robinson

私はこのような答えを組み合わせて使いました:

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

それから私はこれを次のように使います。

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

どうぞ:

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

以下にリストされた拡張方法を使います。私はあなたが開発者にエンコーディングに関して決定を下させるべきであると思うので、関与する魔法が少なくなります。

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

MemoryStream を使用することでメリットが得られると思います。 エンコーディングクラスGetBytes メソッドを使用して取得した文字列バイトでそれを埋めることができます。

8
Konamiman

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

@Shaun Boweの回答に対する@ Palecのコメントに示されているとおりの変更。

6
Nick N.

エンコードを変更する必要がある場合は、@ ShaunBoweのソリューションに投票します。ただし、ここでのすべての回答は、メモリ内の文字列全体を少なくとも1回コピーします。 ToCharArray + BlockCopyコンボでの回答は2回行います。

ここで重要なのは、生のUTF-16文字列用の簡単なStreamラッパーです。 StreamReaderとともに使用する場合は、Encoding.Unicodeを選択します。

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

here は、必要なバインドチェックを備えたより完全なソリューションです(MemoryStreamから派生しているため、ToArrayおよびWriteToメソッドもあります)。

1
György Kőszeg