【问题标题】:Encoding.GetString from an IReadOnlyList<byte>来自 IReadOnlyList<byte> 的 Encoding.GetString
【发布时间】:2013-07-24 21:59:26
【问题描述】:

给定特定的Encoding,有没有办法从IReadOnlyList&lt;byte&gt; 中获取字符串?

更准确地说,有没有办法在将集合的内容传递给 Encoding 对象之前不复制集合的内容?

我主要关心的是性能,其次是内存使用。

【问题讨论】:

  • 如何更精确?
  • 这个问题缺少什么?
  • 也许有人可以解释一下,但我不明白你在追求什么。 is there a way that doesn't copy the content of the collection before passing it to the Encoding object? 是什么意思?
  • @I4V - 我认为他的意思是,他不想像 .ToArray() 那样将字节列表创建为数组的第二个可变副本。
  • @RJProgrammer 你可能是对的,那么答案是否定的。

标签: c# encoding readonly-collection


【解决方案1】:

首先,您必须测试您使用的是单字节编码还是双字节编码。

如果您使用的是单字节编码,您可以简单地 Linq 使用 Select 和 Encoding.GetString(byte); 将字节值直接查询为字符串;

如果您使用双字节编码,您可以一次将两个字节枚举到缓冲区中。由于您会将值类型(字节)重新写入数组元素,因此在此过程中您只会使用两个字节的存储空间,尽管您将复制每个字节。

我认为它看起来像这样,但请注意:我在这台机器上没有编译器,所以我无法验证语法(这是 C#-ish 代码:))

public string example(IReadOnlyList<byte> someListIGotSomewhere, Encoding e)
{
 string retVal = null;
 if(e.IsSingleByte)
 {
     retVal = string.Join("",someListIGotSomewhere.Select(b=>e.GetString(new byte[]{b})));
 }
 else
 {
   StringBuilder sb = new StringBuilder(someListIGotSomewhere.Count()/2);
   var enumerator = someListIGotSomewhere.GetEnumerator();
   var buffer = new byte[2]
   while(enumerator.MoveNext())
   {
     buffer[0] = enumerator.Current;
     buffer[1] = enumerator.MoveNext()?enumerator.Current:0;
     sb.Append(e.GetString(buffer));
   }
   retVal = sb.ToString();
 }
 return retVal;
}

【讨论】:

  • 刚刚想到一件事——你可能不得不考虑编码序言...我已经有一段时间没有在这个“编码”空间玩了...
  • 嗯,否决票来得很快,甚至没有评论......如果答案不好,你能告诉我为什么吗?
  • 虽然我还没有测试过,但我敢打赌这段代码比简单地将列表复制到字节数组要慢得多......(顺便说一句,downvote 不是我的)
  • 不是反对者,但我不相信这段代码适用于 UTF32 编码。
  • 对不起,我会说清楚的
【解决方案2】:

我们现在有人致力于字符串和字节序列的高性能和零拷贝解析。

https://github.com/dotnet/corefxlab/blob/master/docs/specs/parsing.md

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 2017-01-22
    • 1970-01-01
    • 2012-10-02
    相关资源
    最近更新 更多