【问题标题】:C# perform string operation on UTF-16 byte arrayC#对UTF-16字节数组执行字符串操作
【发布时间】:2023-03-27 07:15:01
【问题描述】:

我正在将文件读入byte[] buffer。该文件包含大量 UTF-16 字符串(数百万),格式如下:

  • 第一个字节包含字符和字符串长度(范围 0 .. 255)
  • 以下字节包含UTF-16编码的字符串字符(每个char用2个字节表示,即byteCount = charCount * 2)。

我需要对文件中的所有字符串执行标准字符串操作,例如:IndexOfEndsWithStartsWith,以及StringComparison.OrdinalIgnoreCaseStringComparison.Ordinal

现在我的代码首先将每个字符串从字节数组转换为System.String 类型。我发现下面的代码是最有效的:

// position/length validation removed to minimize the code

string result;
byte charLength = _buffer[_bufferI++];
int byteLength = charLength * 2;

fixed (byte* pBuffer = &_buffer[_bufferI])
{
    result = new string((char*)pBuffer, 0, charLength);
}

_bufferI += byteLength;
return result;

不过,new string(char*, int, int) 还是很慢,因为它执行不必要复制每个字符串

Profiler 说它的 System.String.wstrcpy(char*,char*,int32) 执行缓慢。

我需要一种方法来执行字符串操作无需为每个字符串复制字节

有没有办法直接对字节数组进行字符串操作?

有没有办法创建新字符串而不复制其字节?

【问题讨论】:

  • 并非每个字符都编码为 UTF16 中的两个字节。
  • @Kerrek SB:确实如此,但这些字符也作为多个 char 值存储在字符串中。
  • @Kerrek SB 你在谈论代码点。在 Microsoft 术语中,一个字符是 2 个字节。

标签: c# .net performance string arrays


【解决方案1】:

不,不复制字符数据就无法创建字符串。

String 对象将字符串(长度等)的元数据存储在与字符数据相同的内存区域中,因此您不能将字符数据保留在字节数组中并假装它是String 对象。

您可以尝试从字节数据构造字符串的其他方法,看看它们中的任何一个是否具有较少的开销,例如Encoding.UTF16.GetString

如果您使用的是指针,您可以尝试一次获取多个字符串,这样您就不必为每个字符串修复缓冲区。

【讨论】:

    【解决方案2】:

    您可以使用使用 Encoding.UTF16 的 StreamReader 读取文件,这样您就没有介于两者之间的“字节开销”:

    using (StreamReader sr = new StreamReader(filename, Encoding.UTF16)) 
    {
        string line;
    
        while ((line = sr.ReadLine()) != null) 
        {
            //Your Code
        }
    }
    

    【讨论】:

    • StreamReader 在后台复制缓冲区(在反射器中看到)。
    • @DxCK - 总是有缓冲区副本。你真的试过了吗?
    【解决方案3】:

    您可以在字节数组上创建扩展方法,以直接在字节数组上处理大多数字符串操作,并避免转换成本。不确定您执行的所有字符串操作是什么,因此不确定是否可以通过这种方式完成所有操作。

    【讨论】:

    • 如何以这种方式实现 OrdinalIgnoreCase?
    • 嗯。好问题。这可能需要您将每个字节转换为一个字符并进行比较。这仍然可能比首先将所有项目转换为字符串更快,因为您只需要转换所需的字符数即可使比较操作找到哪一组输入小于或大于另一组。
    猜你喜欢
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    • 2012-02-01
    • 2016-06-30
    • 2010-10-16
    • 2014-02-05
    • 2012-03-25
    相关资源
    最近更新 更多