using System.Globalization;
public static class Program
public static string UnicodeSafeTruncate(this string value, int maxLength)
if (value.Length <= maxLength)
var builder = new StringBuilder();
var builderForward = new StringBuilder();
var textElementEnumerator = StringInfo.GetTextElementEnumerator(value);
while (textElementEnumerator.MoveNext())
builderForward.Append(textElementEnumerator.Current);
if (builderForward.ToString().Length > maxLength)
return builder.ToString();
builder.Append(textElementEnumerator.Current);
public static void Main()
var base64EncodedBytes = System.Convert.FromBase64String("YfCfkanwn4+94oCN8J+akvCfkanwn4+94oCN8J+akmI=");
var value = System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
Console.WriteLine($"Input value: {value} (Length {value.Length})");
var brokenUnicode = value.Substring(0, maxLength);
Console.WriteLine($"Substring Outcome: {brokenUnicode}");
var actualTruncatedString = value.UnicodeSafeTruncate(maxLength);
Console.WriteLine($"UnicodeSafeTruncate Outcome: {actualTruncatedString}");