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
に出力した後、そのコンテンツを文字列として取得できるようにしたいと思います。
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();
}
}
}
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に変更することもできます。
StringWriter を使用して、文字列に値を書き込むことができます。基になるStream
で機能するストリームのような構文を提供します(StringBuilder
から派生しません)。
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
ここには多くの良い答えがありますが、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());
いくつかのオプションがあります:
1つは、ストリームを使用せず、TextWriterを使用することです
void Print(TextWriter writer)
{
}
void Main()
{
var textWriter = new StringWriter();
Print(writer);
string myString = textWriter.ToString();
}
TextWriter
がprint
関数の適切な抽象化レベルである可能性があります。ストリームはバイナリデータの書き込みを目的としていますが、TextWriterは文字列の出力を対象としたより高い抽象化レベルで動作します。
Print
関数もファイルに書き込みたいという動機がある場合は、ファイルストリームからテキストライターを取得することもできます。
void Print(TextWriter writer)
{
}
void PrintToFile(string filePath)
{
using(var textWriter = new StreamWriter(filePath))
{
Print(writer);
}
}
本当にストリームが必要な場合は、MemoryStream
を見ることができます。