如何从字符串生成流?

问:

我需要为采用来自文本文件的流的方法编写单元测试。我想做这样的事情:

Stream s = GenerateStreamFromString("a,b \n c,d");

答1:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

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 方法将关闭 StreamWriter 正在写入的底层 Stream。在这种情况下,这就是我们想要返回的 MemoryStream。

在 .NET 4.5 中,现在 StreamWriter 有一个重载,它在编写器被处置后保持底层流打开,但此代码做同样的事情,并且也适用于其他版本的 .NET。

请参阅Is there any way to close a StreamWriter without closing its BaseStream?

需要指出的一个重要概念是流由字节组成,而字符串由字符组成。理解将字符转换为一个或多个字节(或在本例中为流)始终使用(或假定)特定编码是至关重要的。这个答案虽然在某些情况下是正确的,但使用了默认编码,并且通常可能不适合。将 Encoding 显式传递给 StreamWriter 构造函数将使作者需要考虑 Encoding 的含义更加明显。

您说“不要忘记使用 Using”来使用流,但在您的 GenerateStreamFromString 方法中,您没有将 Using 与 StreamWriter 一起使用。是否有一个原因?

@Ben 是的。如果您处理 StreamWriter,则底层流也将被关闭。我们不希望那样。 Writer 是一次性的唯一原因是为了清理流,所以忽略它是安全的。

还应该注意的是,整个字符串被复制到内存中,这对于大字符串可能很重要,因为现在我们在内存中有一个额外的副本。

@ahong 不是真的。无论如何,StreamWriter 可能正在执行您在内部所说的操作。优点是封装和更简单的代码,但代价是抽象编码之类的东西。这取决于您要达到的目标。

答2:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

另一种解决方案:

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

以防有人将它与 XML 字符串反序列化一起使用,我必须将 UTF8 切换为 Unicode 才能使其在没有标志的情况下工作。好帖子!!!

我比接受的答案更喜欢这个(使用 Rhyous 的调整和微不足道的额外糖用作扩展方法);更灵活,更少的 LOC 和更少的对象(不需要 StreamWriter)

new MemoryStream(Encoding.UTF8.GetBytes("\ufeff" + (value ?? "")) 如果您需要在流的开头包含 BOM

这是非常紧凑的语法,但会导致大量的 byte[] 分配,因此请注意高性能代码。

该解决方案仍然有机会将流设为只读。 new MemoryStream( value, false )。如果必须使用流编写器编写流,则不能将流设为只读。

答3:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

将此添加到静态字符串实用程序类:

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
}

我发现当垃圾收集器清理 StreamWriter 时,返回的流被关闭(导致半随机异常)。解决方法是使用不同的构造函数 - 一个允许我指定 leaveOpen 的构造函数。

不应该处置 StreamWriter 吗?

答4:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

public Stream GenerateStreamFromString(string s)
{
    return new MemoryStream(Encoding.UTF8.GetBytes(s));
}

答5:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

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

按照@Palec 对@Shaun Bowe 答案的评论中的建议进行修改。

或作为单线(@satnhak 建议):

public static Stream ToStream(this string value, Encoding encoding = null) 
    => new MemoryStream((encoding ?? Encoding.UTF8).GetBytes(value ?? string.Empty));

public static Stream ToStream(this string value, Encoding encoding = null) => new MemoryStream((encoding ?? Encoding.UTF8).GetBytes(value ?? string.Empty));

答6:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

我使用了这样的混合答案:

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

托马斯,为什么要投反对票?编码=编码?? Encoding.UTF8 允许我专门询问具有特定编码或默认值 UTF8 的流,并且因为在 .net(就我使用它 .net 4.0 而言)中,您不能在函数中为字符串以外的引用类型提供默认值签名这条线是必要的,这有意义吗?

提到你需要把它放在一个单独的类中(非通用静态类?)也很有帮助并减少反对票。

可以进一步简化为这个吗? public static Stream ToStream(this string str, Encoding enc = Encoding.UTF8) { return new MemoryStream(enc.GetBytes(str ?? "")); }

答7:

huntsbot.com – 高效赚钱,自由工作

使用 MemoryStream 类,首先调用 Encoding.GetBytes 将您的字符串转换为字节数组。

您随后需要在流中添加 TextReader 吗?如果是这样,您可以直接提供 StringReader,并绕过 MemoryStream 和 Encoding 步骤。

答8:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

我们使用下面列出的扩展方法。我认为您应该让开发人员决定编码,因此涉及的魔法更少。

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 ?? ""));
    }
}

我更愿意将第一种方法实现为 return ToStream(s, Encoding.UTF8);。在当前的实现中(return s.ToStream(Encoding.UTF8);,开发人员被迫更加思考以掌握代码,并且似乎s == null的情况未处理并抛出NullReferenceException。

答9:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

如果您需要更改编码,我会投票支持 @ShaunBowe 的解决方案。但是这里的每个答案都至少将整个字符串复制到内存中一次。 ToCharArray + BlockCopy 组合的答案执行两次。

如果这很重要,那么这里是原始 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 方法)。

答10:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

干得好:

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

写入后需要重新设置位置。最好使用构造函数,如 joelnet 的回答。

答11:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

我认为您可以从使用 MemoryStream 中受益。您可以使用 Encoding class 的 GetBytes 方法获得的字符串字节填充它。

原文链接:https://www.huntsbot.com/qa/O6DK/how-do-i-generate-a-stream-from-a-string?lang=zh_CN&from=csdn

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值