中英數文字混雜的定寬切字方法[Big5版]

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