在與很多系統做資料交換,有些交換檔是以Big5編碼固定Bytes的定寬格式,因為在.NET中任何文字包含中英數字或符號都是一個Char,但Big5編碼英文是1Byte、中文是2Byte,所以不能以文字的長度來截字或補空白,小弟我想到的是轉成Bytes來處理。
在與很多系統做資料交換,有些交換檔是以Big5編碼固定Bytes的定寬格式,因為在.NET中任何文字包含中英數字或符號都是一個Char,但Big5編碼英文是1Byte、中文是2Byte,所以不能以文字的長度切字(截字或補空的可參考中英數文字混雜的截字或補空白方法[Big5版]),小弟我想到的是轉成Bytes來處理。
為什麼用轉成Bytes呢?
假設有一規格
| 欄位名稱 | 大小 | 啟始位址 |
| Name | 20 | 0 |
| Phone | 20 | 20 |
二個範例
string eample1 = "Wade 0910123456 "; string eample2 = "黃偉榮 0910123456 "; Console.Write(eample1.Substring(0,20).Trim()); //正確,會輸出"Wade" Console.Write(eample2.Substring(0,20).Trim()); //不正確,會輸出"黃偉榮 091"
因為在.NET中不管幾個Bytes,都算1Char,所以無法直接以Length來處理非1Bytes大小的定寬規格,這時就要轉成Bytes來處理,才會正確。
NOTE:
因為Big5是1-2Bytes動態長度的才有這樣多問題,如果是UTF-16都是2Bytes,就省事多了。
程式碼
public static class ChineseHelper
{
static ChineseHelper()
{
Encoding = Encoding.GetEncoding(950);
}
/// <summary>
/// 將定寬的文字,依Bytes切成陣列,會去空白
/// </summary>
/// <param name="value">定寬文字</param>
/// <param name="separates">每個段落大小</param>
/// <returns></returns>
public static string[] 定寬切字(string value, params int[] separates)
{
if (string.IsNullOrWhiteSpace(value) || (separates == null && separates.Length == 0))
{
return new string[0];
}
List<string> result = new List<string>();
int index = 0;
int currentIndex=0;
var buffer = Encoding.GetBytes(value);
for (int i = 0; i < separates.Length; i++)
{
currentIndex = separates[i];
result.Add(Encoding.GetString(buffer, index, currentIndex).Trim());
index += currentIndex;
}
return result.ToArray();
}
}
測試範例
[TestMethod(), Owner("Wade")]
public void U__ChineseHelper_定寬切字()
{
var result = ChineseHelper.定寬切字("Wade 黃偉榮 在dotblogs點部落 " +
"網址:http://www.dotblogs.com.tw/wadehuang36/Default.aspx ",
50, 50, 100);
Assert.AreEqual("Wade 黃偉榮", result[0]);
Assert.AreEqual("在dotblogs點部落", result[1]);
Assert.AreEqual("網址:http://www.dotblogs.com.tw/wadehuang36/Default.aspx", result[2]);
}