【问题标题】:How to unescape an UTF-8 escaped byte array to an unescaped byte array without allocating a String如何在不分配字符串的情况下将 UTF-8 转义字节数组转义为未转义字节数组
【发布时间】:2019-12-08 14:07:22
【问题描述】:

我有一个 Span<byte> 代表转义字符串 UTF-8,例如:

二进制表示: byte[20] { 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 32, 92, 117, 50, 48, 97, 99, 32, 33 }

转义表示:"Hello world \u20ac !"

所需的二进制结果: byte[17] { 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 32, 226, 130, 172, 32, 33 }

我尝试使用GetString() 方法对转码的\u20ac 进行转码: Encoding.UTF8.GetBytes(Encoding.UTF8.GetString())

但这并不是在逃避输入。

有什么方法可以达到同样的效果吗?

// Not working solution
public void NotWorkingUnescape(ReadOnlySpan<byte> source, Span<byte> destination)
{
    var tmp = Encoding.UTF8.GetString(source);
    Encoding.UTF8.GetBytes(tmp, destination);
}

// Unknown solution
// UTF-8 escaped byte array -> UTF8-8 unescaped byte array
public void FastUnescape(ReadOnlySpan<byte> source, Span<byte> destination)
{
    // ?
}

【问题讨论】:

  • 我尝试了您发布的代码,但没有任何转义。结果与输入相同。
  • 你说得对,我没抓住重点。将更新问题。
  • 解决方案可能来自JsonReader解析器:github.com/dotnet/runtime/blob/…

标签: c# .net performance .net-core utf-8


【解决方案1】:

您是否正在寻找一种可以完成所有工作的方法?

你可以简单地使用这个:

public void FastUnescape(ReadOnlySpan<byte> source, Span<byte> destination)
{
    Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(source), destination);
}

或者防止任何异常:

public void FastUnescape(ReadOnlySpan<byte> source, Span<byte> destination)
{
    if (source.Length <= destination.Length)
    {
        Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(source), destination);
    }
}

更新:

还有另一种方法可以在不使用Encoding.UTF8 的情况下进行转换,通过查看@JonSkeet 响应,您可以实现以下内容:

public static void AnotherMethod(ReadOnlySpan<byte> source, Span<byte> destination)
{
    for (int i = 0; i < source.Length; i++)
    {
        destination[i] = (byte) (Convert.ToChar(source[i]));
    }
}

这段代码的问题是,当使用Convert.toChar时,转换为等效的Unicode字符而不是UTF-8字符,这就是为什么在答案的帖子中使用&amp; 0x7f来获取ASCII 范围。

我没有对您想要转义的其他特殊字符进行性能或功能方面的很多测试,但是我取得了相同的结果

【讨论】:

  • 感谢您的代码,但您的解决方案仍在分配 String。我的目标是避免这种临时分配和操纵。
  • 那个临时值就是转换,在使用GetBytes 方法时你总是必须这样做,我看不到另一种方法,除非你使用另一种完全不同的设计。我已经更新了我的答案
  • 更新后的解决方案对于 ASCII 看起来不错,但正如您所说,对于 UTF-8,这可能不起作用,因为没有 1-1 关系
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-07
  • 2022-01-14
  • 1970-01-01
  • 2016-09-30
  • 1970-01-01
相关资源
最近更新 更多