專案需求常遇到將 DataTable 序列化為字串 (存儲、傳輸) 再還原的情境。本文提供一組可逆轉換方法,採用 XML Schema 保留結構,自訂分隔符區隔資料列與欄位,確保往返無損。
核心邏輯:
DataTable.WriteXmlSchema 寫入 StringWriter 取得結構定義 XML。@&@ 標記結構結束。^&* 分隔,列間以 #$% 分隔 (首列不加列分隔符)。Convert.ToString 處理 DBNull。public static string DataTableToString(DataTable dt) {
StringBuilder strData = new StringBuilder();
using (StringWriter sw = new StringWriter()) {
dt.WriteXmlSchema(sw);
strData.Append(sw.ToString());
}
strData.Append("@&@");
for (int i = 0; i < dt.Rows.Count; i++) {
DataRow row = dt.Rows[i];
if (i > 0) strData.Append("#$%");
for (int j = 0; j < dt.Columns.Count; j++) {
if (j > 0) strData.Append("^&*");
strData.Append(Convert.ToString(row[j]));
}
}
return strData.ToString();
}
還原步驟:
@&@ 分割結構 XML 與資料區。StringReader 讀回 XML Schema 重建 DataTable 結構 (含欄位型別、約束)。#$% 分割列,再以 ^&* 分割欄位,呼叫 DataTable.Rows.Add(object[]) 逐列填入。public static DataTable StringToDataTable(string strdata) {
if (string.IsNullOrEmpty(strdata)) return null;
DataTable dt = new DataTable();
string[] parts = strdata.Split(new[] { "@&@" }, StringSplitOptions.None);
using (StringReader sr = new StringReader(parts[0])) {
dt.ReadXmlSchema(sr);
}
if (parts.Length > 1 && !string.IsNullOrEmpty(parts[1])) {
string[] rows = parts[1].Split(new[] { "#$%" }, StringSplitOptions.None);
foreach (string rowStr in rows) {
string[] cols = rowStr.Split(new[] { "^&*" }, StringSplitOptions.None);
dt.Rows.Add(cols);
}
}
return dt;
}