Как обрезать строку при преобразовании в байты в C #?
Вопрос
Я хотел бы поместить строку в байтовый массив, но строка может быть слишком большой, чтобы уместиться. В случае, если он слишком велик, я бы хотел поместить как можно больше строки в массив. Есть ли эффективный способ узнать, сколько символов поместится?
Решение
Чтобы обрезать строку до байтового массива UTF8 без разделения на середину символа, я использую это:
static string Truncate(string s, int maxLength) {
if (Encoding.UTF8.GetByteCount(s) <= maxLength)
return s;
var cs = s.ToCharArray();
int length = 0;
int i = 0;
while (i < cs.Length){
int charSize = 1;
if (i < (cs.Length - 1) && char.IsSurrogate(cs[i]))
charSize = 2;
int byteSize = Encoding.UTF8.GetByteCount(cs, i, charSize);
if ((byteSize + length) <= maxLength){
i = i + charSize;
length += byteSize;
}
else
break;
}
return s.Substring(0, i);
}
Затем возвращаемая строка может быть безопасно передана в байтовый массив длины maxLength.
Другие советы
Вы должны использовать класс Encoding для правильного преобразования в байтовый массив? Все объекты кодирования имеют переопределенный метод GetMaxCharCount, который выдаст вам «максимальное количество символов, полученное при декодировании указанного количества байтов». Вы должны быть в состоянии использовать это значение, чтобы обрезать вашу строку и правильно ее кодировать.
Эффективным способом было бы найти, сколько (пессимистически) байтов вам понадобится на символ с
Encoding.GetMaxByteCount(1);
затем делим размер строки на результат, затем конвертируем столько символов с помощью
public virtual int Encoding.GetBytes (
string s,
int charIndex,
int charCount,
byte[] bytes,
int byteIndex
)
Если вы хотите использовать меньше памяти, используйте
Encoding.GetByteCount(string);
но это гораздо более медленный метод.
Класс Encoding в .NET имеет метод с именем GetByteCount
, который может принимать строку или символ []. Если вы передадите 1 символ, он скажет вам, сколько байтов необходимо для этого 1 символа в любой кодировке, которую вы используете.
Метод GetMaxByteCount
работает быстрее, но он выполняет вычисление в худшем случае, которое может вернуть большее число, чем фактически необходимо.
Куки, твой код не делает того, о чем ты думаешь. Предварительное выделение байтового буфера в вашем случае является пустой тратой, потому что он не будет использоваться. Скорее, ваше назначение удаляет выделенную память и сбрасывает ссылку arr
для указания на другой буфер, потому что Encoding.GetBytes
возвращает новый массив.