【问题标题】:StringStream in C#C#中的字符串流
【发布时间】:2011-12-29 22:24:01
【问题描述】:

我希望能够从我创建的派生自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 后,我希望能够将其内容作为字符串检索。

【问题讨论】:

  • 您是否考虑改用StringBuilder
  • 如果Stream 不代表string 会怎样?你到底想用这样的东西达到什么目的?
  • 能否提供外部 API 方法的签名?

标签: c# .net stringstream


【解决方案1】:

您可以串联使用MemoryStreamStreamReader 类:

void Main()
{
    string myString;

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

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

【讨论】:

    【解决方案2】:

    既然您的 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());
      }
      ... 
    
    }
    

    您可能希望将 UTF8 更改为 ASCII,具体取决于 Print() 使用的编码。

    【讨论】:

    • GetBuffer() 为我返回带有零尾的整个缓冲区。 ToArray() 对我有用。
    • @Fox32:注意ToArray() 创建了一个新数组,而GetBuffer() 返回内部数组。
    • 此答案适用于从流中获取字符串。对于逆向(从字符串中获取流),您可以执行 var stream = new MemoryStream(Encoding.UTF8.GetBytes("string"));
    【解决方案3】:

    您可以使用StringWriter 将值写入字符串。它提供了一种类似于流的语法(尽管不是从 Stream 派生的),可与底层 StringBuilder 一起使用。

    【讨论】:

    • 我不明白为什么这个答案被接受,因为它不能解决发帖人的问题。 StringWriter 不是 Stream,因此不能用作一个。
    • @Neutrino OP 的代码不需要使用Stream - 在这种情况下这是一个更好的设计选择。
    • 我阅读了 OP 的声明“外部 dll 中的方法打印。我需要使用 Stream”表示 Print 是无法修改的外部代码,或者其他设计约束要求使用 Stream in这是方法签名。在这种情况下,重构 Print 的签名并不能回答所述问题,尽管问题可能只是措辞模棱两可。
    • 我来这里是为了寻找字符串流,而不是字符串编写器
    • @Isaac 这直接回答了原发帖人的问题。如果您尝试将字符串读取为Stream,则可以使用msdn.microsoft.com/en-us/library/…
    【解决方案4】:

    您可以从字符串创建 MemoryStream 并将其用于任何需要流的第三方函数。在这种情况下,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
    

    【讨论】:

    • 我想我会发布一个与标题真正匹配的答案,因为这是大多数人来这里寻找的。​​span>
    【解决方案5】:

    我在这里看到了很多好的答案,但没有一个能直接解决 C# 中缺少 StringStream 类的问题。所以我自己写了一篇……

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

    【讨论】:

      【解决方案6】:

      您有多种选择:

      一个是不使用流,而是使用TextWriter

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

      TextWriter 可能是您的print 函数的适当抽象级别。 Streams 旨在写入二进制数据,而 TextWriter 工作在更高的抽象级别,专门用于输出字符串。

      如果您的动机是还希望您的 Print 函数写入文件,您也可以从文件流中获取文本写入器。

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

      如果你真的想要一个流,你可以查看MemoryStream

      【讨论】:

      猜你喜欢
      • 2011-03-29
      • 1970-01-01
      • 2014-08-08
      • 1970-01-01
      • 1970-01-01
      • 2012-01-04
      • 1970-01-01
      • 1970-01-01
      • 2013-09-24
      相关资源
      最近更新 更多