web-dev-qa-db-ja.com

C#のStringStream

Streamから派生した、作成したクラスから文字列を構築できるようにしたい。具体的には、次のようなコードを記述できるようにします。

void Print(Stream stream) {
    // Some code that operates on a Stream.
}

void Main() {
    StringStream stream = new StringStream();
    Print(stream);
    string myString = stream.GetResult();
}

これを可能にするStringStreamというクラスを作成できますか?または、そのようなクラスはすでに利用可能ですか?

更新:私の例では、メソッドPrintはサードパーティの外部DLLで提供されています。ご覧のとおり、Printが期待する引数はStreamです。 Streamに出力した後、そのコンテンツを文字列として取得できるようにしたいと思います。

44
AndreyAkinshin

MemoryStream および StreamReader クラスのタンデムを使用できます。

void Main()
{
    string myString;

    using (var stream = new MemoryStream())
    {
        Print(stream);

        stream.Position = 0;
        using (var reader = new StreamReader(stream))
        {
            myString = reader.ReadToEnd();
        }
    }
}
37
Lu55

Print()メソッドはおそらくテキストデータを処理するので、TextWriterパラメーターを受け入れるように書き換えることができますか?

ライブラリはStringWriter: TextWriterが、StringStreamではありません。 MemoryStreamをラップすることで作成できると思いますが、本当に必要ですか?


更新後:

void Main() 
{
  string myString;  // outside using

  using (MemoryStream stream = new MemoryStream ())
  {
     Print(stream);
     myString = Encoding.UTF8.GetString(stream.ToArray());
  }
  ... 

}

Print()で使用されるエンコーディングに応じて、UTF8をASCIIに変更することもできます。

35
Henk Holterman

StringWriter を使用して、文字列に値を書き込むことができます。基になるStreamで機能するストリームのような構文を提供します(StringBuilderから派生しません)。

12
Reed Copsey

StringからMemoryStreamを作成し、それをrequiresストリームであるサードパーティ関数で使用できます。この場合、MemoryStreamはUTF8.GetBytesの助けを借りて、JavaのStringStreamの機能を提供します。

文字列の例から

String content = "stuff";
using (MemoryStream stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(content)))
{
    Print(stream); //or whatever action you need to perform with the stream
    stream.Seek(0, SeekOrigin.Begin); //If you need to use the same stream again, don't forget to reset it.
    UseAgain(stream);
}

文字列への例

stream.Seek(0, SeekOrigin.Begin);
string s;
using (var readr = new StreamReader(stream))
{
    s = readr.ReadToEnd();
}
//and don't forget to dispose the stream if you created it
4
NH.

ここには多くの良い答えがありますが、C#のStringStreamクラスの欠如に直接対処するものはありません。だから私は自分の1つを書いた...

public class StringStream : Stream
{
    private readonly MemoryStream _memory;
    public StringStream(string text)
    {
        _memory = new MemoryStream(Encoding.UTF8.GetBytes(text));
    }
    public StringStream()
    {
        _memory = new MemoryStream();
    }
    public StringStream(int capacity)
    {
        _memory = new MemoryStream(capacity);
    }
    public override void Flush()
    {
        _memory.Flush();
    }
    public override int Read(byte[] buffer, int offset, int count)
    {
        return  _memory.Read(buffer, offset, count);
    }
    public override long Seek(long offset, SeekOrigin Origin)
    {
        return _memory.Seek(offset, Origin);
    }
    public override void SetLength(long value)
    {
        _memory.SetLength(value);
    }
    public override void Write(byte[] buffer, int offset, int count)
    {
        _memory.Write(buffer, offset, count);
        return;
    }
    public override bool CanRead => _memory.CanRead;
    public override bool CanSeek => _memory.CanSeek;
    public override bool CanWrite => _memory.CanWrite;
    public override long Length =>  _memory.Length;
    public override long Position
    {
        get => _memory.Position;
        set => _memory.Position = value;
    }
    public override string ToString()
    {
        return System.Text.Encoding.UTF8.GetString(_memory.GetBuffer(), 0, (int) _memory.Length);
    }
    public override int ReadByte()
    {
        return _memory.ReadByte();
    }
    public override void WriteByte(byte value)
    {
        _memory.WriteByte(value);
    }
}

その使用例...

        string s0 =
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\r\n" +
            "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud\r\n" +
            "exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor\r\n" +
            "in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint\r\n" +
            "occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\r\n";
        StringStream ss0 = new StringStream(s0);
        StringStream ss1 = new StringStream();
        int line = 1;
        Console.WriteLine("Contents of input stream: ");
        Console.WriteLine();
        using (StreamReader reader = new StreamReader(ss0))
        {
            using (StreamWriter writer = new StreamWriter(ss1))
            {
                while (!reader.EndOfStream)
                {
                    string s = reader.ReadLine();
                    Console.WriteLine("Line " + line++ + ": " + s);
                    writer.WriteLine(s);
                }
            }
        }

        Console.WriteLine();
        Console.WriteLine("Contents of output stream: ");
        Console.WriteLine();
        Console.Write(ss1.ToString());
3
AQuirky

いくつかのオプションがあります:

1つは、ストリームを使用せず、TextWriterを使用することです

   void Print(TextWriter writer) 
   {
   }

   void Main() 
  {
    var textWriter = new StringWriter();
    Print(writer);
    string myString = textWriter.ToString();
   }

TextWriterprint関数の適切な抽象化レベルである可能性があります。ストリームはバイナリデータの書き込みを目的としていますが、TextWriterは文字列の出力を対象としたより高い抽象化レベルで動作します。

Print関数もファイルに書き込みたいという動機がある場合は、ファイルストリームからテキストライターを取得することもできます。

void Print(TextWriter writer) 
{
}

void PrintToFile(string filePath) 
{
     using(var textWriter = new StreamWriter(filePath))
     {
         Print(writer);
     }
}

本当にストリームが必要な場合は、MemoryStreamを見ることができます。

2
Andrew Shepherd