优化实体列表二进制序列化和Csv读写

This commit is contained in:
智能大石头 2025-07-15 15:16:24 +08:00
parent 9cb2d74957
commit 238ca5c36a
2 changed files with 48 additions and 30 deletions

View File

@ -1164,7 +1164,7 @@ public static class EntityExtension
#endregion #endregion
#region #region
/// <summary>转为DbTable</summary> /// <summary>实体列表转为DbTable</summary>
/// <param name="list">实体列表</param> /// <param name="list">实体列表</param>
/// <returns></returns> /// <returns></returns>
public static DbTable ToTable<T>(this IEnumerable<T> list) where T : IEntity public static DbTable ToTable<T>(this IEnumerable<T> list) where T : IEntity
@ -1204,7 +1204,7 @@ public static class EntityExtension
return dt; return dt;
} }
/// <summary>写入数据流</summary> /// <summary>实体列表以二进制序列化写入数据流</summary>
/// <param name="list">实体列表</param> /// <param name="list">实体列表</param>
/// <param name="stream">数据流</param> /// <param name="stream">数据流</param>
/// <returns></returns> /// <returns></returns>
@ -1212,6 +1212,7 @@ public static class EntityExtension
{ {
if (list == null) return 0; if (list == null) return 0;
//todo Binary需要字段记录已经写入多少字节部分数据流不支持Position
var bn = new Binary { Stream = stream, EncodeInt = true, FullTime = true }; var bn = new Binary { Stream = stream, EncodeInt = true, FullTime = true };
var p = stream.Position; var p = stream.Position;
foreach (var entity in list) foreach (var entity in list)
@ -1285,9 +1286,7 @@ public static class EntityExtension
if (list == null) return 0; if (list == null) return 0;
var compressed = file.EndsWithIgnoreCase(".gz"); var compressed = file.EndsWithIgnoreCase(".gz");
return displayfields != null return file.AsFile().OpenWrite(compressed, fs => SaveCsv(list, fs, fields, displayfields));
? file.AsFile().OpenWrite(compressed, fs => SaveCsv(list, fs, fields, displayfields))
: file.AsFile().OpenWrite(compressed, fs => SaveCsv(list, fs, fields));
} }
/// <summary>写入文件Csv格式</summary> /// <summary>写入文件Csv格式</summary>
@ -1308,28 +1307,43 @@ public static class EntityExtension
} }
/// <summary>从数据流读取列表</summary> /// <summary>从数据流读取实体列表</summary>
/// <param name="list">实体列表</param> /// <param name="factory">实体工厂</param>
/// <param name="stream">数据流</param> /// <param name="stream">数据流</param>
/// <returns>实体列表</returns> /// <returns>实体列表</returns>
public static IEnumerable<T> Read<T>(this IList<T> list, Stream stream) where T : IEntity public static IEnumerable<IEntity> Read(this IEntityFactory factory, Stream stream)
{ {
if (stream == null) yield break; if (factory == null || stream == null) yield break;
var bn = new Binary { Stream = stream, EncodeInt = true, FullTime = true }; var bn = new Binary { Stream = stream, EncodeInt = true, FullTime = true };
var fact = typeof(T).AsFactory();
while (stream.Position < stream.Length) while (stream.Position < stream.Length)
{ {
var entity = (T)fact.Create(); var entity = factory.Create();
if (entity is IAccessor acc) acc.Read(stream, bn); if (entity is IAccessor acc) acc.Read(stream, bn);
list.Add(entity);
yield return entity; yield return entity;
} }
} }
/// <summary>从文件读取列表,二进制格式</summary> /// <summary>从文件读取实体列表,二进制格式</summary>
/// <param name="factory">实体工厂</param>
/// <param name="file">文件</param>
/// <returns>实体列表</returns>
public static IEnumerable<IEntity> LoadFile(this IEntityFactory factory, String file)
{
if (file.IsNullOrEmpty()) return [];
file = file.GetFullPath();
if (!File.Exists(file)) return [];
Stream fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
if (file.EndsWithIgnoreCase(".gz"))
fs = new GZipStream(fs, CompressionMode.Decompress);
return Read(factory, fs);
}
/// <summary>从文件读取实体列表,二进制格式</summary>
/// <param name="list">实体列表</param> /// <param name="list">实体列表</param>
/// <param name="file">文件</param> /// <param name="file">文件</param>
/// <returns>实体列表</returns> /// <returns>实体列表</returns>
@ -1339,22 +1353,21 @@ public static class EntityExtension
file = file.GetFullPath(); file = file.GetFullPath();
if (!File.Exists(file)) return list; if (!File.Exists(file)) return list;
Stream fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read); var factory = typeof(T).AsFactory();
var bn = new Binary { Stream = fs, EncodeInt = true, FullTime = true }; foreach (var entity in factory.LoadFile(file))
{
list.Add((T)entity);
}
if (file.EndsWithIgnoreCase(".gz")) return list;
fs = new GZipStream(fs, CompressionMode.Decompress);
return Read(list, fs).ToList();
} }
/// <summary>从数据流读取列表Csv格式</summary> /// <summary>从数据流读取实体列表Csv格式</summary>
/// <param name="list">实体列表</param> /// <param name="factory">实体工厂</param>
/// <param name="stream">数据流</param> /// <param name="stream">数据流</param>
/// <returns>实体列表</returns> /// <returns>实体列表</returns>
public static IEnumerable<T> LoadCsv<T>(this IList<T> list, Stream stream) where T : IEntity public static IEnumerable<IEntity> LoadCsv(this IEntityFactory factory, Stream stream)
{ {
var fact = typeof(T).AsFactory();
using var csv = new CsvFile(stream, true); using var csv = new CsvFile(stream, true);
// 匹配字段 // 匹配字段
@ -1364,7 +1377,7 @@ public static class EntityExtension
var fields = new FieldItem[names.Length]; var fields = new FieldItem[names.Length];
for (var i = 0; i < names.Length; i++) for (var i = 0; i < names.Length; i++)
{ {
fields[i] = fact.Fields.FirstOrDefault(e => names[i].EqualIgnoreCase(e.Name, e.DisplayName, e.ColumnName)); fields[i] = factory.Fields.FirstOrDefault(e => names[i].EqualIgnoreCase(e.Name, e.DisplayName, e.ColumnName));
} }
// 读取数据 // 读取数据
@ -1373,15 +1386,13 @@ public static class EntityExtension
var line = csv.ReadLine(); var line = csv.ReadLine();
if (line == null || line.Length == 0) break; if (line == null || line.Length == 0) break;
var entity = (T)fact.Create(); var entity = factory.Create();
for (var i = 0; i < fields.Length && i < line.Length; i++) for (var i = 0; i < fields.Length && i < line.Length; i++)
{ {
var fi = fields[i]; var fi = fields[i];
if (fi != null && !line[i].IsNullOrEmpty()) entity.SetItem(fi.Name, line[i].ChangeType(fi.Type)); if (fi != null && !line[i].IsNullOrEmpty()) entity.SetItem(fi.Name, line[i].ChangeType(fi.Type));
} }
list.Add(entity);
yield return entity; yield return entity;
} }
} }
@ -1397,7 +1408,14 @@ public static class EntityExtension
if (!File.Exists(file)) return list; if (!File.Exists(file)) return list;
var compressed = file.EndsWithIgnoreCase(".gz"); var compressed = file.EndsWithIgnoreCase(".gz");
file.AsFile().OpenRead(compressed, fs => LoadCsv(list, fs).ToList()); file.AsFile().OpenRead(compressed, fs =>
{
var factory = typeof(T).AsFactory();
foreach (var entity in factory.LoadCsv(fs))
{
list.Add((T)entity);
}
});
return list; return list;
} }

View File

@ -1150,7 +1150,7 @@ public partial class Area : Entity<Area>
stream = new GZipStream(stream, CompressionMode.Decompress, true); stream = new GZipStream(stream, CompressionMode.Decompress, true);
stream = new BufferedStream(stream); stream = new BufferedStream(stream);
} }
list.LoadCsv(stream); list = Meta.Factory.LoadCsv(stream).Cast<Area>().ToList();
} }
else else
list.LoadCsv(csvFile); list.LoadCsv(csvFile);