在與很多系統做資料交換,有些交換檔是以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]); }