C#判斷字串的顯示寬度
起因:
公司有一個使用專案使用HTML轉換為PDF,其中有一個表格,表格的最後一列中的單元格,其字串超長後會被丟棄,而不是換行到下一行展示(HtmlToPdf渲染引擎導致的,沒辦法更改)
解決方案:
根據字串長度手動新增<br/>
換行
var source = "ABCD";
if (GetLength(source)>2)
{
source = source.Insert(2,"<br/>");
}
Console.WriteLine(source);
// 輸出AB<br/>CD
int GetLength(string src)
{
return src.Length;
}
出現了一個BUG:
當原始內容中存在中文時,中文字元的顯示寬度大於英文字元的寬度,按照字串中的字元數進行處理,並不準確
/*
* 中文:中文<br/>CD
* 英文:AB<br/>CD
*/
原因分析:
在文字的顯示中,有全形和半形的區別
全形:指一個字元佔用兩個標準字元位置的狀態。
半形:指一個字元佔用一個標準字元位置的狀態。
嘗試解決:
字元編碼:最早的字元編碼為Ascii碼,只考慮了英文語種使用者,後來隨著計算機的普及,有了其他編碼,比如GB2312、UTF8等,不止包含英文的字元編碼,但是這些編碼都對Ascii碼進行了相容
沒有細心求證的結論:Ascii碼對應的是半形,中文擴充套件部分是全形展示,半形顯示寬度為全形的一半(這結論是我猜的,沒有求證,如果不對還請提出批評指正)
透過上面猜測的結論,可以先對每個字元判斷是不是Ascii字元來決定當前是全形還是半形
var source = "ABCD";
var index =InserAtDisplayWidth(2,source);
if (index!=-1)
{
source = source.Insert(index,"<br/>");
}
// AB<br/>CD
Console.WriteLine(source);
var source2 = "中文CD";
var index2 =InserAtDisplayWidth(2,source2);
if (index2!=-1)
{
source2 = source2.Insert(index2,"<br/>");
}
// 中<br/>文CD
Console.WriteLine(source2);
int InserAtDisplayWidth(int inserAtDisplayWidth, string source){
int now =0;
for (int i = 0; i < source.Length; i++)
{
if( char.IsAscii(source[i])){
// 半形佔一個顯示寬度
now +=1;
}else{
// 全形佔兩個顯示寬度
now +=2;
};
if (now>inserAtDisplayWidth)
{
return i;
}
}
return -1;
}
透過對字元的判斷,更加準確的匹配了分隔的位置,既避免了無效的空白區域,又避免了過長的字串溢位導致看不到內容
/*
* AB<br/>CD
* 中<br/>文CD
*/