forked from szgit/Helper.Core.Library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TxtHelper.cs
512 lines (480 loc) · 23.5 KB
/
TxtHelper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
/*
* 作用:读取/写入文档数据。
* 联系:QQ 100101392
* 来源:https://github.com/snipen/Helper.Core.Library
* */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
namespace Helper.Core.Library
{
#region 逻辑辅助枚举
public enum TxtTypeEnum
{
/// <summary>
/// 实体带有 TxtT 特性
/// </summary>
Attribute = 1,
/// <summary>
/// 实体不带有 TxtT 特性
/// </summary>
Normal = 2,
}
#endregion
public class TxtHelper
{
#region 私有属性常量
public const string NewLine = "\r\n";
#endregion
#region 对外公开方法
#region Read
/// <summary>
/// 读取 Txt 数据
/// </summary>
/// <param name="path">路径</param>
/// <returns></returns>
public static string Read(string path)
{
return Read(path, System.Text.Encoding.UTF8);
}
/// <summary>
/// 读取 Txt 数据
/// </summary>
/// <param name="path">路径</param>
/// <param name="encoding">编码格式</param>
/// <returns></returns>
public static string Read(string path, System.Text.Encoding encoding)
{
string content = "";
ExecuteStreamReader(path, encoding, (StreamReader streamReader) =>
{
content = streamReader.ReadToEnd();
});
return content;
}
#endregion
#region Write
/// <summary>
/// 数据写入 Txt 文件
/// </summary>
/// <param name="path">路径</param>
/// <param name="content">要写入的数据</param>
/// <param name="append">是否追加</param>
/// <returns></returns>
public static bool Write(string path, string content, bool append = false)
{
return Write(path, content, append, System.Text.Encoding.UTF8);
}
/// <summary>
/// 数据写入 Txt 文件
/// </summary>
/// <param name="path">路径</param>
/// <param name="content">要写入的数据</param>
/// <param name="append">是否追加</param>
/// <param name="encoding">编码格式</param>
/// <returns></returns>
public static bool Write(string path, string content, bool append, System.Text.Encoding encoding)
{
return ExecuteStreamWriter(path, encoding, append, () =>
{
return content;
});
}
#endregion
#region ToEntityList<T>
/// <summary>
/// 返回实体数据列表
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="txtPath">Txt 路径</param>
/// <param name="splitChar">列分隔符,例:|</param>
/// <param name="propertyMatchList">属性匹配,Dictionary<string, object> 或 new {}</param>
/// <param name="typeEnum">TxtTypeEnum 枚举类型</param>
/// <param name="lineSplitChar">行分隔符,例:\r\n</param>
/// <param name="reflectionType">反射类型</param>
/// <returns></returns>
public static List<T> ToEntityList<T>(string txtPath, string splitChar, object propertyMatchList = null, TxtTypeEnum typeEnum = TxtTypeEnum.Normal, string lineSplitChar = NewLine, ReflectionTypeEnum reflectionType = ReflectionTypeEnum.Expression) where T : class, new()
{
return ToEntityList<T>(txtPath, splitChar, System.Text.Encoding.UTF8, propertyMatchList, typeEnum, lineSplitChar, reflectionType);
}
/// <summary>
/// 返回实体数据列表
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="txtPath">Txt 路径</param>
/// <param name="splitChar">列分隔符,例:|</param>
/// <param name="encoding">编码格式</param>
/// <param name="propertyMatchList">属性匹配,Dictionary<string, object> 或 new {}</param>
/// <param name="typeEnum">TxtTypeEnum 枚举类型</param>
/// <param name="lineSplitChar">行分隔符,例:\r\n</param>
/// <param name="reflectionType">反射类型</param>
/// <returns></returns>
public static List<T> ToEntityList<T>(string txtPath, string splitChar, System.Text.Encoding encoding, object propertyMatchList = null, TxtTypeEnum typeEnum = TxtTypeEnum.Normal, string lineSplitChar = NewLine, ReflectionTypeEnum reflectionType = ReflectionTypeEnum.Expression) where T : class, new()
{
List<T> dataList = new List<T>();
ExecuteStreamReader(txtPath, encoding, (StreamReader streamReader) =>
{
Dictionary<string, object> propertyDict = CommonHelper.GetParameterDict(propertyMatchList);
Dictionary<PropertyInfo, int> propertyNameDict = InitTxtToEntityMapper<T>(propertyDict, typeEnum);
dynamic propertySetDict = null;
if (reflectionType != ReflectionTypeEnum.Original) propertySetDict = ReflectionExtendHelper.PropertySetCallDict<T>(reflectionType);
string content = streamReader.ReadToEnd();
string[] contentList = content.Split(new string[] { lineSplitChar }, StringSplitOptions.None);
foreach (string contentItem in contentList)
{
dataList.Add(TextToEntity<T>(contentItem, splitChar, propertySetDict, propertyNameDict));
}
});
return dataList;
}
/// <summary>
/// 返回字典数据
/// </summary>
/// <typeparam name="T">基类类型,例:string</typeparam>
/// <typeparam name="K">基类类型,例:int</typeparam>
/// <param name="txtPath">Txt 路径</param>
/// <param name="splitChar">列分隔符,例:|</param>
/// <param name="lineSplitChar">行分隔符,例:\r\n</param>
/// <param name="keyIndex">键索引,默认:0</param>
/// <param name="valueIndex">值索引,默认:1</param>
/// <returns></returns>
public static Dictionary<T, K> ToDict<T, K>(string txtPath, string splitChar, string lineSplitChar = NewLine, int keyIndex = 0, int valueIndex = 1)
{
return ToDict<T, K>(txtPath, splitChar, System.Text.Encoding.UTF8, lineSplitChar, keyIndex, valueIndex);
}
/// <summary>
/// 返回字典数据
/// </summary>
/// <typeparam name="T">基类类型,例:string</typeparam>
/// <typeparam name="K">基类类型,例:int</typeparam>
/// <param name="txtPath">Txt 路径</param>
/// <param name="splitChar">列分隔符,例:|</param>
/// <param name="encoding">编码格式</param>
/// <param name="lineSplitChar">行分隔符,例:\r\n</param>
/// <param name="keyIndex">键索引,默认:0</param>
/// <param name="valueIndex">值索引,默认:1</param>
/// <returns></returns>
public static Dictionary<T, K> ToDict<T, K>(string txtPath, string splitChar, System.Text.Encoding encoding, string lineSplitChar = NewLine, int keyIndex = 0, int valueIndex = 1)
{
Dictionary<T, K> resultDict = new Dictionary<T, K>();
ExecuteStreamReader(txtPath, encoding, (StreamReader streamReader) =>
{
string content = streamReader.ReadToEnd();
string[] contentList = content.Split(new string[] { lineSplitChar }, StringSplitOptions.None);
foreach (string contentItem in contentList)
{
string[] itemList = contentItem.Split(new string[] { splitChar }, StringSplitOptions.None);
if (!string.IsNullOrEmpty(itemList[keyIndex]))
{
resultDict.Add((T)Convert.ChangeType(itemList[keyIndex], typeof(T)), (K)Convert.ChangeType(itemList[valueIndex], typeof(K)));
}
}
});
return resultDict;
}
/// <summary>
/// 返回基础类型数据列表
/// </summary>
/// <typeparam name="T">基类类型,例:string</typeparam>
/// <param name="txtPath">Txt 路径</param>
/// <param name="splitChar">列分隔符,例:|</param>
/// <param name="lineSplitChar">行分隔符,例:\r\n</param>
/// <param name="fieldIndex">字段索引,默认:0</param>
/// <returns></returns>
public static List<T> ToList<T>(string txtPath, string splitChar, string lineSplitChar = NewLine, int fieldIndex = 0)
{
return ToList<T>(txtPath, splitChar, System.Text.Encoding.UTF8, lineSplitChar, fieldIndex);
}
/// <summary>
/// 返回基础类型数据列表
/// </summary>
/// <typeparam name="T">基类类型,例:string</typeparam>
/// <param name="txtPath">Txt 路径</param>
/// <param name="splitChar">列分隔符,例:|</param>
/// <param name="encoding">编码格式</param>
/// <param name="lineSplitChar">行分隔符,例:\r\n</param>
/// <param name="fieldIndex">字段索引,默认:0</param>
/// <returns></returns>
public static List<T> ToList<T>(string txtPath, string splitChar, System.Text.Encoding encoding, string lineSplitChar = NewLine, int fieldIndex = 0)
{
List<T> dataList = new List<T>();
ExecuteStreamReader(txtPath, encoding, (StreamReader streamReader) =>
{
string content = streamReader.ReadToEnd();
string[] contentList = content.Split(new string[] { lineSplitChar }, StringSplitOptions.None);
if (splitChar == lineSplitChar)
{
foreach (string contentItem in contentList)
{
dataList.Add((T)Convert.ChangeType(contentItem, typeof(T)));
}
}
else
{
foreach (string contentItem in contentList)
{
string[] itemList = contentItem.Split(new string[] { splitChar }, StringSplitOptions.None);
dataList.Add((T)Convert.ChangeType(itemList[fieldIndex], typeof(T)));
}
}
});
return dataList;
}
#endregion
#region ToTxt<T>
/// <summary>
/// 列表数据写入 Txt
/// </summary>
/// <typeparam name="T">普通类型,例:int</typeparam>
/// <param name="txtPath">Txt 路径</param>
/// <param name="dataList">数据列表</param>
/// <param name="splitChar">列分隔符,例:|</param>
/// <returns></returns>
public static bool ToTxt<T>(string txtPath, List<T> dataList, string splitChar)
{
return ToTxt<T>(txtPath, dataList, splitChar, System.Text.Encoding.UTF8);
}
/// <summary>
/// 列表数据写入 Txt
/// </summary>
/// <typeparam name="T">普通类型,例:int</typeparam>
/// <param name="txtPath">Txt 路径</param>
/// <param name="dataList">数据列表</param>
/// <param name="splitChar">列分隔符,例:|</param>
/// <param name="encoding">编码格式</param>
/// <returns></returns>
public static bool ToTxt<T>(string txtPath, List<T> dataList, string splitChar, System.Text.Encoding encoding)
{
bool result = ExecuteStreamWriter(txtPath, encoding, false, () =>
{
return StringHelper.ToString<T>(dataList, splitChar);
});
return result;
}
/// <summary>
/// 实体对象数据写入 Txt
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="txtPath">Txt 路径</param>
/// <param name="dataList">实体数据列表</param>
/// <param name="splitChar">列分隔符,例:|</param>
/// <param name="typeEnum">TxtTypeEnum 枚举类型</param>
/// <param name="propertyMatchList">属性匹配,Dictionary<string, object> 或 new {}</param>
/// <param name="propertyList">属性列表,如果指定,则按指定属性列表生成文本数据</param>
/// <param name="propertyContain">是否包含,true 属性包含,flase 属性排除</param>
/// <param name="lineSplitChar">行分隔符,例:\r\n</param>
/// <param name="reflectionType">反射类型</param>
/// <returns></returns>
public static bool ToTxt<T>(string txtPath, List<T> dataList, string splitChar, TxtTypeEnum typeEnum, object propertyMatchList = null, string[] propertyList = null, bool propertyContain = true, string lineSplitChar = NewLine, ReflectionTypeEnum reflectionType = ReflectionTypeEnum.Expression) where T : class
{
return ToTxt<T>(txtPath, dataList, splitChar, System.Text.Encoding.UTF8, typeEnum, propertyMatchList, propertyList, propertyContain, lineSplitChar, reflectionType);
}
/// <summary>
/// 实体对象数据写入 Txt
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="txtPath">Txt 路径</param>
/// <param name="dataList">实体数据列表</param>
/// <param name="splitChar">列分隔符,例:|</param>
/// <param name="typeEnum">TxtTypeEnum 枚举类型</param>
/// <param name="encoding">编码格式</param>
/// <param name="propertyMatchList">属性匹配,Dictionary<string, object> 或 new {}</param>
/// <param name="propertyList">属性列表,如果指定,则按指定属性列表生成文本数据</param>
/// <param name="lineSplitChar">行分隔符,例:\r\n</param>
/// <param name="reflectionType">反射类型</param>
/// <returns></returns>
public static bool ToTxt<T>(string txtPath, List<T> dataList, string splitChar, System.Text.Encoding encoding, TxtTypeEnum typeEnum, object propertyMatchList = null, string[] propertyList = null, bool propertyContain = true, string lineSplitChar = NewLine, ReflectionTypeEnum reflectionType = ReflectionTypeEnum.Expression) where T : class
{
bool result = ExecuteStreamWriter(txtPath, encoding, false, () =>
{
StringBuilder stringBuilder = new StringBuilder();
Dictionary<int, PropertyInfo> propertyNameDict = InitEntityToTxtMapper<T>(propertyMatchList, typeEnum, propertyList, propertyContain);
List<int> propertyIndexList = propertyNameDict.Keys.ToList<int>();
propertyIndexList.Sort((int x, int y) =>
{
if (x > y) return 1;
if (x < y) return -1;
return 0;
});
dynamic propertyGetDict = null;
if (reflectionType != ReflectionTypeEnum.Original) propertyGetDict = ReflectionExtendHelper.PropertyGetCallDict<T>(reflectionType);
foreach (T t in dataList)
{
stringBuilder.Append(EntityToText<T>(t, splitChar, propertyGetDict, propertyNameDict, propertyIndexList, lineSplitChar));
}
return stringBuilder.ToString();
});
return result;
}
#endregion
#endregion
#region 逻辑处理私有方法
private static void ExecuteStreamReader(string txtPath, System.Text.Encoding encoding, Action<StreamReader> callback)
{
using (StreamReader streamReader = new StreamReader(txtPath, encoding))
{
if (callback != null) callback(streamReader);
}
}
private static bool ExecuteStreamWriter(string txtPath, System.Text.Encoding encoding, bool append, Func<string> callback)
{
// 根据路径创建目录
bool createDirectoryStatus = FileHelper.CreateDirectory(txtPath);
if (!createDirectoryStatus) return false;
string content = null;
if (callback != null) content = callback();
using (StreamWriter streamWriter = new StreamWriter(txtPath, append, encoding))
{
streamWriter.Write(content);
streamWriter.Flush();
}
return true;
}
#region ToEntity
private static T TextToEntity<T>(string text, string splitChar, dynamic propertySetDict, Dictionary<PropertyInfo, int> propertyNameDict) where T : class, new()
{
// 按分隔符拆分文本内容
string[] dataList = text.Split(new string[] { splitChar }, StringSplitOptions.None);
T t = ReflectionGenericHelper.New<T>();
foreach (var keyValueItem in propertyNameDict)
{
if (keyValueItem.Value >= 0 && keyValueItem.Value < dataList.Length)
{
// 设置实体对象属性数据
if (propertySetDict != null && propertySetDict.ContainsKey(keyValueItem.Key.Name))
{
ReflectionGenericHelper.SetPropertyValue(propertySetDict[keyValueItem.Key.Name], t, dataList[keyValueItem.Value], keyValueItem.Key);
}
else
{
ReflectionHelper.SetPropertyValue(t, dataList[keyValueItem.Value], keyValueItem.Key);
}
}
}
return t;
}
private static Dictionary<PropertyInfo, int> InitTxtToEntityMapper<T>(Dictionary<string, object> propertyMatch = null, TxtTypeEnum typeEnum = TxtTypeEnum.Normal) where T : class
{
int propertyIndex = 0;
Dictionary<PropertyInfo, int> propertyDict = new Dictionary<PropertyInfo, int>();
ReflectionGenericHelper.Foreach<T>((PropertyInfo propertyInfo) =>
{
if (propertyMatch != null && propertyMatch.ContainsKey(propertyInfo.Name))
{
propertyDict.Add(propertyInfo, int.Parse(propertyMatch[propertyInfo.Name].ToString()));
}
else
{
if (typeEnum == TxtTypeEnum.Attribute)
{
TxtTAttribute attribute = propertyInfo.GetCustomAttribute<TxtTAttribute>();
if (attribute != null && (attribute.Type == AttributeReadAndWriteTypeEnum.ReadAndWrite || attribute.Type == AttributeReadAndWriteTypeEnum.Read))
{
propertyDict.Add(propertyInfo, attribute.Index);
}
}
else
{
propertyDict.Add(propertyInfo, propertyIndex);
propertyIndex++;
}
}
});
return propertyDict;
}
#endregion
#region ToTxt
private static string EntityToText<T>(T t, string splitChar, dynamic propertyGetDict, Dictionary<int, PropertyInfo> propertyNameDict, List<int> propertyIndexList, string lineSplitChar = NewLine) where T : class
{
Type type = typeof(T);
object propertyValue = null;
StringBuilder stringBuilder = new StringBuilder();
int count = propertyIndexList.Count;
for (int index = 0; index < count; index++)
{
string propertyName = propertyNameDict[propertyIndexList[index]].Name;
if (propertyGetDict != null && propertyGetDict.ContainsKey(propertyName))
{
propertyValue = propertyGetDict[propertyName](t);
}
else
{
propertyValue = ReflectionHelper.GetPropertyValue(t, propertyName);
}
if (propertyValue != null) stringBuilder.Append(propertyValue.ToString());
if (index < count - 1)
{
stringBuilder.Append(splitChar);
}
}
stringBuilder.Append(lineSplitChar);
return stringBuilder.ToString();
}
private static Dictionary<int, PropertyInfo> InitEntityToTxtMapper<T>(object propertyMatchList = null, TxtTypeEnum typeEnum = TxtTypeEnum.Normal, string[] propertyList = null, bool propertyContain = true) where T : class
{
List<string> filterNameList = null;
if (propertyList != null) filterNameList = propertyList.ToList<string>();
int propertyIndex = 0;
Dictionary<string, object> propertyMatchDict = CommonHelper.GetParameterDict(propertyMatchList);
Dictionary<int, PropertyInfo> propertyNameDict = new Dictionary<int, PropertyInfo>();
ReflectionGenericHelper.Foreach<T>((PropertyInfo propertyInfo) =>
{
if (filterNameList == null || (propertyContain && filterNameList.IndexOf(propertyInfo.Name) >= 0) || (!propertyContain && filterNameList.IndexOf(propertyInfo.Name) < 0))
{
if (propertyMatchDict != null && propertyMatchDict.ContainsKey(propertyInfo.Name))
{
propertyNameDict.Add(int.Parse(propertyMatchDict[propertyInfo.Name].ToString()), propertyInfo);
}
else
{
if (typeEnum == TxtTypeEnum.Attribute)
{
TxtTAttribute attribute = propertyInfo.GetCustomAttribute<TxtTAttribute>();
if (attribute != null && (attribute.Type == AttributeReadAndWriteTypeEnum.ReadAndWrite || attribute.Type == AttributeReadAndWriteTypeEnum.Write))
{
object attributeIndex = ReflectionExtendHelper.GetAttributeValue<TxtTAttribute>(typeof(T), propertyInfo, p => p.Index);
if (attributeIndex != null) propertyNameDict.Add(int.Parse(attributeIndex.ToString()), propertyInfo);
}
}
else
{
propertyNameDict.Add(propertyIndex, propertyInfo);
propertyIndex++;
}
}
}
});
return propertyNameDict;
}
#endregion
#endregion
}
#region 逻辑处理辅助特性
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class TxtTAttribute : Attribute
{
private int index;
private AttributeReadAndWriteTypeEnum type;
/// <summary>
/// 实体属性映射 Txt 列索引
/// </summary>
/// <param name="index">列索引,索引 从 1 开始</param>
public TxtTAttribute(int index, AttributeReadAndWriteTypeEnum type = AttributeReadAndWriteTypeEnum.ReadAndWrite)
{
this.index = index;
this.type = type;
}
/// <summary>
/// 实体属性所对应的 Txt 列索引,索引 从 1 开始
/// </summary>
public int Index { get { return this.index; } }
/// <summary>
/// 是否写入
/// </summary>
public AttributeReadAndWriteTypeEnum Type { get { return this.type; } }
}
#endregion
}