C# 按字节截断字符串
trim string to the specified number of bytes
把字符串转成字节数组后,截断至特定长度时,可能会导致尾部乱码,可以使用以下方法进行安全截断
foreach (var encode in
new Encoding[]{
Encoding.UTF8,
Encoding.Unicode,
Encoding.Default
}
)
{
Console.WriteLine($"-----------------\r\n{encode.EncodingName}");
byte[] bs = encode.GetBytes(ss);
for (int i = 1; i < bs.Length; i++)
{
byte[] result = trimStringBytes(ss, encode, i);
Console.WriteLine($"截断为{i}个字节时,有效字节数:{result.Length},完整的字符串是:{encode.GetString(result)}");
}
}
/// <summary>
/// 截断字符串字节数组
/// </summary>
/// <param name="ss"></param>
/// <param name="encoding"></param>
/// <param name="len">需要得到的长度</param>
/// <param name="bs">处理后的数组</param>
/// <returns></returns>
public static byte[] trimStringBytes( string ss, System.Text.Encoding encoding, int len)
{
if (len == 0)
{
return new byte[0];
}
byte[] bs = encoding.GetBytes(ss);
if (len >= bs.Length)
{
Array.Resize(ref bs, len);
return bs;
}
char[] cc = ss.ToCharArray();
int c = encoding.GetCharCount(bs, 0, len); //涉及了C个字符
int m = encoding.GetByteCount(cc, 0, c); //计算C个字符串应当使用的字节数
// 如果当前截断导致字符串不完整(小于m),减1
if (m == len)
{
Array.Resize(ref bs, len);
return bs;
}
else
{
Array.Resize(ref bs, encoding.GetByteCount(cc, 0, c - 1));
return bs;
}
}
@@#
输出结果
Unicode (UTF-8)
截断为1个字节时,有效字节数:0,完整的字符串是:
截断为2个字节时,有效字节数:0,完整的字符串是:
截断为3个字节时,有效字节数:3,完整的字符串是:单
截断为4个字节时,有效字节数:3,完整的字符串是:单
截断为5个字节时,有效字节数:3,完整的字符串是:单
截断为6个字节时,有效字节数:6,完整的字符串是:单位
截断为7个字节时,有效字节数:7,完整的字符串是:单位c
截断为8个字节时,有效字节数:8,完整的字符串是:单位cm
截断为9个字节时,有效字节数:8,完整的字符串是:单位cm
截断为10个字节时,有效字节数:8,完整的字符串是:单位cm
截断为11个字节时,有效字节数:11,完整的字符串是:单位cm!
截断为12个字节时,有效字节数:12,完整的字符串是:单位cm!1
截断为13个字节时,有效字节数:13,完整的字符串是:单位cm!12
-----------------
Unicode
截断为1个字节时,有效字节数:0,完整的字符串是:
截断为2个字节时,有效字节数:2,完整的字符串是:单
截断为3个字节时,有效字节数:2,完整的字符串是:单
截断为4个字节时,有效字节数:4,完整的字符串是:单位
截断为5个字节时,有效字节数:4,完整的字符串是:单位
截断为6个字节时,有效字节数:6,完整的字符串是:单位c
截断为7个字节时,有效字节数:6,完整的字符串是:单位c
截断为8个字节时,有效字节数:8,完整的字符串是:单位cm
截断为9个字节时,有效字节数:8,完整的字符串是:单位cm
截断为10个字节时,有效字节数:10,完整的字符串是:单位cm!
截断为11个字节时,有效字节数:10,完整的字符串是:单位cm!
截断为12个字节时,有效字节数:12,完整的字符串是:单位cm!1
截断为13个字节时,有效字节数:12,完整的字符串是:单位cm!1
截断为14个字节时,有效字节数:14,完整的字符串是:单位cm!12
截断为15个字节时,有效字节数:14,完整的字符串是:单位cm!12
-----------------
简体中文(GB2312)
截断为1个字节时,有效字节数:0,完整的字符串是:
截断为2个字节时,有效字节数:2,完整的字符串是:单
截断为3个字节时,有效字节数:2,完整的字符串是:单
截断为4个字节时,有效字节数:4,完整的字符串是:单位
截断为5个字节时,有效字节数:5,完整的字符串是:单位c
截断为6个字节时,有效字节数:6,完整的字符串是:单位cm
截断为7个字节时,有效字节数:6,完整的字符串是:单位cm
截断为8个字节时,有效字节数:8,完整的字符串是:单位cm!
截断为9个字节时,有效字节数:9,完整的字符串是:单位cm!1
截断为10个字节时,有效字节数:10,完整的字符串是:单位cm!12
Java 中的写法
public static byte[] trimStringBytes(String ss, Charset encoding, int len) {
if (len == 0) {
return new byte[0];
}
ByteBuffer bs = encoding.encode(ss);
if (len >= bs.remaining()) {
byte[] result = new byte[len];
bs.get(result, 0, bs.remaining());
return result;
}
bs.limit(len);//限制可读长度
CharBuffer cb = CharBuffer.allocate(len);
CharsetDecoder cd = encoding.newDecoder();
// Ignore an incomplete character
cd.onMalformedInput(CodingErrorAction.IGNORE);
cd.decode(bs, cb, true);
cd.flush(cb);
String s = new String(cb.array(), 0, cb.position());
ByteBuffer nf = encoding.encode(s);
byte[] result = new byte[nf.remaining()];
nf.get(result);
return result;
}
@@#