Aqui estão duas soluções possíveis - um LINQ one-liner processando a entrada da esquerda para a direita e um tradicional
for
-loop processando a entrada da direita para a esquerda. Qual direção de processamento é mais rápida depende do comprimento da string, do comprimento de byte permitido e do número e distribuição de caracteres multibyte e é difícil dar uma sugestão geral. A decisão entre o LINQ e o código tradicional provavelmente é uma questão de gosto (ou talvez velocidade). Se a velocidade é importante, pode-se pensar em apenas acumular o comprimento do byte de cada caractere até atingir o comprimento máximo, em vez de calcular o comprimento do byte de toda a string em cada iteração. Mas não tenho certeza se isso funcionará porque não conheço a codificação UTF-8 bem o suficiente. Eu poderia teoricamente imaginar que o comprimento de byte de uma string não é igual à soma dos comprimentos de byte de todos os caracteres.
public static String LimitByteLength(String input, Int32 maxLength)
{
return new String(input
.TakeWhile((c, i) =>
Encoding.UTF8.GetByteCount(input.Substring(0, i + 1)) <= maxLength)
.ToArray());
}
public static String LimitByteLength2(String input, Int32 maxLength)
{
for (Int32 i = input.Length - 1; i >= 0; i--)
{
if (Encoding.UTF8.GetByteCount(input.Substring(0, i + 1)) <= maxLength)
{
return input.Substring(0, i + 1);
}
}
return String.Empty;
}