有一个项目,要对一串文本按字节长度进行分割,这串文本包含中英文字符,如果按C#中的string.Length属性得到字符串长度,那么一个汉字的长度只能算一个,这样就得不到正确的字节长度,从而也就无法正确分割字符串了。
没有找到什么好方法,只好手工处理了,代码如下:
using System;
using System.Text.RegularExpressions;
using System.Text;
namespace CTest
{
class Program
{
static void Main(string[] args)
{
string str = "中12345国6734长城56789中34国长城5678912中34国长城5678912中34国长城56789";
Console.WriteLine(str);
Console.WriteLine();
string strInf = SplitString(str);
Console.WriteLine(strInf);
Console.Read();
}
// 按字节数对字符串进行分割
static string SplitString(string str)
{
byte[] strByte = Encoding.Default.GetBytes(str);
int nLeftCount = strByte.Length; // 末处理字节数
int nCurBytesPos = 0; // 当前字节位置
int nMaxBytesNum = 8; // 行最大字节数
int CurRowBytesNum; // 当前行所取字节数
string strInf = "";
while (true)
{
if (nLeftCount == 0) break;
// 末处理字节数已不够一行最大字节数
if (nLeftCount < nMaxBytesNum)
{
strInf += Encoding.Default.GetString(strByte, nCurBytesPos, nLeftCount);
break;
}
// 末处理字节数已超过一行最大字节数, 先计算当前行应取的最大字节数
if (bIsHZHalfBytes(strByte, nCurBytesPos + nMaxBytesNum - 1)) // 当前行最后一个字节是否是汉字的一半
{
CurRowBytesNum = nMaxBytesNum - 1; // 如果是半个汉字,则最后一个字节本行不要,留给下一行处理
}
else
{
CurRowBytesNum = nMaxBytesNum;
}
// 按本行的最大数量,得到字符串
string s1 = Encoding.Default.GetString(strByte, nCurBytesPos, CurRowBytesNum) + "\r\n";
// 如果行的字节数量没有达到最大数量,则对字符串进行格式化整理
// 在汉字和ASCII码之间插入一个空格, 这样排版美观
if (CurRowBytesNum != nMaxBytesNum)
{
for (int i = 0; i < CurRowBytesNum; i++)
{
if (strByte[nCurBytesPos + i] < 0x8f)
{
if(i>0)
s1 = s1.Insert(i-1, " ");
else
s1 = s1.Insert(i, " ");
break;
}
}
}
strInf += s1;
nCurBytesPos += CurRowBytesNum;
nLeftCount -= CurRowBytesNum;
}
return strInf;
}
// 判断byte[]缓冲区中,指定位置的字节,是否为汉字的半字节
static bool bIsHZHalfBytes(byte[] pBuf, int nPos)
{
if (pBuf[nPos] < 0x80) return false; // 如果最后一个字节是ASCII码,则返回false
int nCount = 0;
// 计算末尾的汉字的字节数
while (pBuf[nPos] >= 0x80)
{
nCount++;
nPos--;
if (nPos < 0) break;
}
// 如果末尾的汉字的字节是奇数,说明最后一个字节只取了汉字的一半
return (nCount % 2) != 0;
}
}
}
程序运行如下: