C#对UTF-16字节数组执行字符串操作

时间:2011-06-25 11:27:17

标签: c# .net performance string arrays

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

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

我需要对文件中的所有字符串执行标准字符串操作,例如:IndexOfEndsWithStartsWithStringComparison.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)执行缓慢。

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

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

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

3 个答案:

答案 0 :(得分:2)

不,如果不复制字符数据,则无法创建字符串。

String对象将字符串的元数据(Length,et.c。)存储在与字符数据相同的内存区域中,因此您无法将字符数据保留在字节数组中并假装它是String对象。

您可以尝试其他方法从字节数据构造字符串,并查看其中是否有任何开销较少,如Encoding.UTF16.GetString

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

答案 1 :(得分:0)

您可以使用Encoding.UTF16使用StreamReader读取文件,因此您之间没有“字节开销”:

using (StreamReader sr = new StreamReader(filename, Encoding.UTF16)) 
{
    string line;

    while ((line = sr.ReadLine()) != null) 
    {
        //Your Code
    }
}

答案 2 :(得分:0)

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