c# DbfHelper 幫助類
阿新 • • 發佈:2021-08-24
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.IO; using System.Linq; using System.Reflection; using System.Text; namespace FastDBF { public class DbfHelper { private static readonly string basePath = Directory.GetCurrentDirectory();public static (bool, string) WriteDdf<T>(T model, string dbfName) where T : class { List<T> ts = new List<T>(); ts.Add(model); return WriteDdf<T>(model, dbfName); } /// <summary> /// 寫入dbf /// </summary>/// <typeparam name="T"></typeparam> /// <param name="list">列表資料</param> /// <param name="dbfPath">dbf儲存路徑</param> /// <returns></returns> public static (bool, string) WriteDdf<T>(List<T> list, string dbfName) whereT : class { if (list == null) return (false, "傳入資料為空"); DbfFile dbfFile = new DbfFile(Encoding.UTF8); try { //建立dbf檔案 string writeDirectory = Path.Combine(basePath, "DbfFile"); string writePath = Path.Combine(writeDirectory, dbfName); if (!Directory.Exists(writeDirectory)) Directory.CreateDirectory(writeDirectory); bool fileIsExists = File.Exists(writePath); dbfFile.Open(writePath, FileMode.Append, FileAccess.Write); dbfFile._headerWritten = fileIsExists; var dicProperty = Mapping<T>(); //create a header foreach (var it in dicProperty) { dbfFile.Header.AddColumn(new DbfColumn(it.Key, DbfColumn.DbfColumnType.Character, 255, 0)); } foreach (var it in list) { var orec = new DbfRecord(dbfFile.Header) { AllowDecimalTruncate = true }; foreach (var col in dicProperty) { var pro = col.Value; object value = pro.GetValue(it); if (value == null || value == DBNull.Value) { value = ""; } orec[col.Key] = value.ToString(); } dbfFile.Write(orec, true); } dbfFile.Dispose(); return (true, "寫入成功"); } catch (Exception ex) { dbfFile.Dispose(); return (false, $"寫入失敗:{ex.ToString()}"); } } /// <summary> /// 讀取dbf檔案 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dbfPath">dbf檔案路徑</param> /// <returns></returns> public static (bool, List<T>, string) ReadDdf<T>(string dbfName) where T : class { List<T> list = new List<T>(); DbfFile dbfFile = new DbfFile(Encoding.UTF8); try { //獲取一個DBF檔案物件 string readPath = Path.Combine(basePath, "DbfFile", dbfName); if (!File.Exists(readPath)) return (false, null, "檔案不存在"); dbfFile.Open(readPath, FileMode.Open, FileAccess.Read); var dicProperty = Mapping<T>(); //讀取dbf的欄位名 DbfHeader dh = dbfFile.Header; List<string> dbfColumns = new List<string>(); for (int index = 0; index < dh.ColumnCount; index++) { dbfColumns.Add(dh[index].Name); } //讀取資料 int i = 0; while (dbfFile.Read(i) != null) { //讀取一行 DbfRecord record = dbfFile.Read(i); if (record == null) { continue; } T t = Activator.CreateInstance<T>(); foreach (var col in dbfColumns) { var data = dicProperty.FirstOrDefault(r => r.Key == col); if (data.Key == null) { continue; } var pro = data.Value; if (pro == null || !pro.CanWrite) { continue; } string value = record[col]; if (value == null) { continue; } pro.SetValue(t, Convert.ChangeType(value.Trim(), pro.PropertyType)); } list.Add(t); i++; } dbfFile.Close(); return (true, list, ""); } catch (Exception ex) { dbfFile.Dispose(); return (false, null, $"讀取失敗:{ex.ToString()}"); } } /// <summary> /// 對映 /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> private static List<KeyValuePair<string, PropertyInfo>> Mapping<T>() where T : class { Type type = typeof(T); var properties = type.GetProperties(); List<KeyValuePair<string, PropertyInfo>> result = new List<KeyValuePair<string, PropertyInfo>>(); //儲存dbf欄位和實體的對映關係 //實體沒有ColumnAttribute,則認為dbf欄位名稱和實體名稱一致 foreach (var pro in properties) { var attrs = pro.GetCustomAttributes(true).SingleOrDefault(attr => attr.GetType().Name == typeof(ColumnAttribute).Name) as dynamic; if (attrs == null) result.Add(new KeyValuePair<string, PropertyInfo>(pro.Name, pro)); else result.Add(new KeyValuePair<string, PropertyInfo>(attrs.Name, pro)); } return result; } } }