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) where T : 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; } } }