C # выполняет строковую операцию над байтовым массивом UTF-16 - PullRequest
0 голосов
/ 25 июня 2011

Я читаю файл в byte[] buffer. Файл содержит много строк UTF-16 (миллионов) в следующем формате:

  • Первый байт содержит и длину строки в символах (диапазон 0 .. 255)
  • Следующие байты содержат строковые символы в кодировке UTF-16 (каждый символ, представленный 2 байтами, означает byteCount = charCount * 2).

Мне нужно выполнить стандартные строковые операции для всех строк в файле, например: IndexOf, EndsWith и StartsWith, с StringComparison.OrdinalIgnoreCase и StringComparison.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) это очень медленно, потому что он выполняет ненужных копирование для каждой строки .

Профилировщик говорит, что System.String.wstrcpy(char*,char*,int32) работает медленно.

Мне нужен способ выполнения строковых операций без копирования байтов для каждой строки .

Есть ли способ выполнить строковые операции с байтовым массивом напрямую ?

Есть ли способ создать новую строку без копирования ее байтов?

Ответы [ 3 ]

2 голосов
/ 25 июня 2011

Нет, вы не можете создать строку без копирования символьных данных.

Объект String хранит метаданные для строки (длина и т. Д.) В той же области памяти, что и символьные данные, поэтому вы не можете хранить символьные данные в байтовом массиве и притворяться, что они String объект.

Вы можете попробовать другие способы построения строки из байтовых данных и посмотреть, имеет ли какой-либо из них меньше служебных данных, например Encoding.UTF16.GetString.

Если вы используете указатель, вы можете попытаться получить несколько строк одновременно, чтобы вам не приходилось фиксировать буфер для каждой строки.

0 голосов
/ 25 июня 2011

Вы можете создать методы расширения для байтовых массивов, чтобы обрабатывать большинство этих строковых операций непосредственно в байтовом массиве и избежать затрат на преобразование. Не уверен, какие все строковые операции вы выполняете, поэтому не уверен, что все они могут быть выполнены таким образом.

0 голосов
/ 25 июня 2011

Вы можете прочитать файл с помощью StreamReader, используя Encoding.UTF16, чтобы у вас не было промежуточных байтов:

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

    while ((line = sr.ReadLine()) != null) 
    {
        //Your Code
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...