来源:https://www.cnblogs.com/lxhbky/p/12219080.html
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 | using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; namespace StockCheckApp.Utils { public sealed class CsvHelper { private static readonly CsvHelper instance = new CsvHelper(); public static CsvHelper getInstance() { return instance; } /// <summary> /// 日志 /// </summary> //private ILogger _Logger { get; set; } //public CsvHelper(ILogger<CsvHelper> logger) //{ // this._Logger = logger; //} private CsvHelper() { } public List<T> Read<T>( string filePath, CsvFileDescription fileDescription) where T : class , new () { List<T> tList = new List<T>(50 * 10000); T t = null ; int currentRawIndex = 0; if (File.Exists(filePath)) { using (StreamReader streamReader = new StreamReader(filePath, fileDescription.Encoding)) { Dictionary< int , FieldMapper> fieldMapperDic = FieldMapper.GetModelFieldMapper<T>().ToDictionary(m => m.CSVTitleIndex); string rawValue = null ; string [] rawValueArray = null ; PropertyInfo propertyInfo = null ; string propertyValue = null ; bool rawReadEnd = false ; bool isExistSplitChart = false ; do { rawValue = streamReader.ReadLine(); //标题行 if (currentRawIndex > fileDescription.TitleRawIndex) { if (! string .IsNullOrEmpty(rawValue)) { //替换字符串含有分隔符为{分隔符},最后再替换回来 if (rawValue.Contains( "\"" )) { isExistSplitChart = true ; int yhBeginIndex = 0; int yhEndIndex = 0; string yhText = null ; do { yhBeginIndex = StringHelper.GetIndexOfStr(rawValue, "\"" , 1); yhEndIndex = StringHelper.GetIndexOfStr(rawValue, "\"" , 2); yhText = rawValue.Substring(yhBeginIndex, (yhEndIndex - yhBeginIndex + 1)); string newYHText = yhText.Replace( "\"" , "" ).Replace(fileDescription.SeparatorChar.ToString(), "{分隔符}" ); rawValue = rawValue.Replace(yhText, newYHText); } while (rawValue.Contains( "\"" )); } rawValueArray = rawValue.Split(fileDescription.SeparatorChar); t = new T(); foreach ( var fieldMapper in fieldMapperDic) { propertyInfo = fieldMapper.Value.PropertyInfo; propertyValue = rawValueArray[fieldMapper.Key]; if (! string .IsNullOrEmpty(propertyValue)) { try { if (isExistSplitChart && propertyValue.Contains( "{分隔符}" )) { propertyValue = propertyValue.Replace( "{分隔符}" , fileDescription.SeparatorChar.ToString()); } TypeHelper.SetPropertyValue(t, propertyInfo.Name, propertyValue); } catch (Exception e) { string msg = $ "第{currentRawIndex + 1}行数据{propertyValue}转换属性{propertyInfo.Name}-{propertyInfo.PropertyType.Name}失败!" ; //this._Logger.LogWarning(e, msg); //continue; throw new Exception(msg); } } } tList.Add(t); } else { rawReadEnd = true ; } } currentRawIndex++; } while (rawReadEnd == false ); } } return tList; } public void WriteFile<T>( string path, List<T> tList, CsvFileDescription fileDescription) where T : class , new () { if (! string .IsNullOrEmpty(path)) { string fileDirectoryPath = null ; if (path.Contains( "\\" )) { fileDirectoryPath = path.Substring(0, path.LastIndexOf( '\\' )); } else { fileDirectoryPath = path.Substring(0, path.LastIndexOf( '/' )); } if (!Directory.Exists(fileDirectoryPath)) { Directory.CreateDirectory(fileDirectoryPath); } int dataCount = tList.Count; Dictionary< int , FieldMapper> fieldMapperDic = FieldMapper.GetModelFieldMapper<T>().ToDictionary(m => m.CSVTitleIndex); int titleCount = fieldMapperDic.Keys.Count; //.Max(); string [] rawValueArray = new string [titleCount]; StringBuilder rawValueBuilder = new StringBuilder(); string rawValue = null ; T t = null ; PropertyInfo propertyInfo = null ; int currentRawIndex = 0; int tIndex = 0; using (StreamWriter streamWriter = new StreamWriter(path, false , fileDescription.Encoding)) { do { try { rawValue = "" ; #if DEBUG if (currentRawIndex % 10000 == 0) { string msg = $ "已写入文件:{path},数据量:{currentRawIndex}" ; //this._Logger.LogInformation(msg); } #endif if (currentRawIndex >= fileDescription.TitleRawIndex) { //清空数组数据 for ( int i = 0; i < titleCount; i++) { rawValueArray[i] = "" ; } if (currentRawIndex > fileDescription.TitleRawIndex) { t = tList[tIndex]; tIndex++; } foreach ( var fieldMapperItem in fieldMapperDic) { //写入标题行 if (currentRawIndex == fileDescription.TitleRawIndex) { rawValueArray[fieldMapperItem.Key] = fieldMapperItem.Value.CSVTitle; } //真正的数据从标题行下一行开始写 else { propertyInfo = fieldMapperItem.Value.PropertyInfo; object propertyValue = propertyInfo.GetValue(t); string formatValue = null ; if (propertyValue != null ) { if (propertyInfo.PropertyType is IFormattable && ! string .IsNullOrEmpty(fieldMapperItem.Value.OutputFormat)) { formatValue = ((IFormattable)propertyValue).ToString(fieldMapperItem.Value.OutputFormat, null ); } else { formatValue = propertyValue.ToString(); } //如果属性值含有分隔符,则使用双引号包裹 if (formatValue.Contains(fileDescription.SeparatorChar.ToString())) { formatValue = $ "\"{formatValue}\"" ; } rawValueArray[fieldMapperItem.Key] = formatValue; } } } rawValue = string .Join(fileDescription.SeparatorChar, rawValueArray); } rawValueBuilder.Append(rawValue + "\r\n" ); } catch (Exception e) { string msg = $ "(异常)Excel第{currentRawIndex + 1}行,数据列表第{tIndex + 1}个数据写入失败!rawValue:{rawValue}" ; //this._Logger.LogWarning(e, msg); throw new Exception(msg); } currentRawIndex++; } while (tIndex < dataCount); streamWriter.Write(rawValueBuilder.ToString()); streamWriter.Close(); streamWriter.Dispose(); } } } } } |
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 | using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; namespace StockCheckApp.Utils { /// <summary> /// 字段映射类 /// </summary> public class FieldMapper { /// <summary> /// 属性信息 /// </summary> public PropertyInfo PropertyInfo { get ; set ; } /// <summary> /// 标题 /// </summary> public string CSVTitle { get ; set ; } /// <summary> /// 标题下标位置 /// </summary> public int CSVTitleIndex { get ; set ; } /// <summary> /// 字符输出格式(数字和日期类型需要) /// </summary> public string OutputFormat { get ; set ; } public static List<FieldMapper> GetModelFieldMapper<T>() { List<FieldMapper> fieldMapperList = new List<FieldMapper>(100); List<PropertyInfo> tPropertyInfoList = typeof (T).GetProperties().ToList(); CsvColumnAttribute csvColumnAttribute = null ; foreach ( var tPropertyInfo in tPropertyInfoList) { csvColumnAttribute = (CsvColumnAttribute)tPropertyInfo.GetCustomAttribute( typeof (CsvColumnAttribute)); if (csvColumnAttribute != null ) { fieldMapperList.Add( new FieldMapper { PropertyInfo = tPropertyInfo, CSVTitle = csvColumnAttribute.Title, CSVTitleIndex = csvColumnAttribute.TitleIndex, OutputFormat = csvColumnAttribute.OutputFormat }); } } return fieldMapperList; } } } using System; using System.Collections.Generic; using System.Text; namespace StockCheckApp.Utils { public class StringHelper { /// <summary> /// 获取字符串中第strPosition个位置的str的下标 /// </summary> /// <param name="text"></param> /// <param name="str"></param> /// <param name="strPosition"></param> /// <returns></returns> public static int GetIndexOfStr( string text, string str, int strPosition) { int strIndex = -1; int currentPosition = 0; if (! string .IsNullOrEmpty(text) && ! string .IsNullOrEmpty(str) && strPosition >= 1) { do { currentPosition++; if (strIndex == -1) { strIndex = text.IndexOf(str); } else { strIndex = text.IndexOf(str, strIndex + 1); } } while (currentPosition < strPosition); } return strIndex; } } } using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; namespace StockCheckApp.Utils { /// <summary> /// 类型帮助类 /// </summary> public class TypeHelper { private static Dictionary<Type, List<PropertyInfo>> _TypePropertyDic = new Dictionary<Type, List<PropertyInfo>>(0); /// <summary> /// 获取T属性列表 /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public static List<PropertyInfo> GetTPropertyDic<T>() { Type tType = typeof (T); List<PropertyInfo> propertyInfoList = null ; if (TypeHelper._TypePropertyDic.ContainsKey(tType)) { propertyInfoList = TypeHelper._TypePropertyDic[tType]; } else { propertyInfoList = tType.GetProperties().ToList(); TypeHelper._TypePropertyDic.Add(tType, propertyInfoList); } return propertyInfoList; } /// <summary> /// 获取t属性值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="t"></param> /// <param name="propertyName"></param> /// <returns></returns> public static object GetPropertyValue<T>(T t, string propertyName) { object value = null ; Type tType = typeof (T); List<PropertyInfo> propertyInfoList = TypeHelper.GetTPropertyDic<T>(); PropertyInfo propertyInfo = propertyInfoList.FirstOrDefault(m => m.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); if (propertyInfo != null ) { value = propertyInfo.GetValue(t); } return value; } /// <summary> /// 设置t属性值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="t"></param> /// <param name="propertyName"></param> /// <param name="propertyValue"></param> public static void SetPropertyValue<T>(T t, string propertyName, object propertyValue) { Type tType = typeof (T); List<PropertyInfo> propertyInfoList = TypeHelper.GetTPropertyDic<T>(); PropertyInfo propertyInfo = propertyInfoList.FirstOrDefault(m => m.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); if (propertyInfo != null && propertyValue != null ) { if (!propertyInfo.PropertyType.IsGenericType) { propertyInfo.SetValue(t, Convert.ChangeType(propertyValue, propertyInfo.PropertyType)); } else { Type genericTypeDefinition = propertyInfo.PropertyType.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof (Nullable<>)) { propertyInfo.SetValue(t, Convert.ChangeType(propertyValue, Nullable.GetUnderlyingType(propertyInfo.PropertyType))); } } } } /// <summary> /// 克隆相同属性数据到另一个类列表中 /// </summary> /// <typeparam name="Tin"></typeparam> /// <typeparam name="Tout"></typeparam> /// <param name="inList"></param> /// <returns></returns> public static List<Tout> CloneData<Tin, Tout>(List<Tin> inList) where Tout : new () { List<Tout> outList = new List<Tout>(0); if (inList != null && inList.Count > 0) { Dictionary< string , PropertyInfo> inTProList = TypeHelper.GetTPropertyDic<Tin>().ToDictionary(m => m.Name); Dictionary< string , PropertyInfo> outTProList = TypeHelper.GetTPropertyDic<Tout>().ToDictionary(m => m.Name); Tout outT = default (Tout); foreach ( var item in inList) { outT = new Tout(); foreach ( var inProItem in inTProList) { if (outTProList.ContainsKey(inProItem.Key)) { outTProList[inProItem.Key].SetValue(outT, inProItem.Value.GetValue(item)); } } outList.Add(outT); } } return outList; } } } using System; using System.Collections.Generic; using System.Text; namespace StockCheckApp.Utils { /// <summary> /// Csv文件类特性标记 /// </summary> [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = false )] public class CsvColumnAttribute : System.Attribute { internal const int defaultTitleIndex = Int32.MaxValue; /// <summary> /// 标题 /// </summary> public string Title { get ; set ; } /// <summary> /// 标题位置(从0开始) /// </summary> public int TitleIndex { get ; set ; } /// <summary> /// 字符输出格式(数字和日期类型需要) /// </summary> public string OutputFormat { get ; set ; } public CsvColumnAttribute() { Title = "" ; TitleIndex = defaultTitleIndex; OutputFormat = "" ; } public CsvColumnAttribute( string title, int titleIndex, string outputFormat) { Title = title; TitleIndex = titleIndex; OutputFormat = outputFormat; } } } using System; using System.Collections.Generic; using System.Text; namespace StockCheckApp.Utils { public class CsvFileDescription { public CsvFileDescription() : this (0) { } public CsvFileDescription( int titleRawIndex) : this ( ',' , titleRawIndex, Encoding.UTF8) { } public CsvFileDescription( char separatorChar, int titleRawIndex, Encoding encoding) { this .SeparatorChar = separatorChar; this .TitleRawIndex = titleRawIndex; this .Encoding = encoding; } /// <summary> /// CSV文件字符编码 /// </summary> public Encoding Encoding { get ; set ; } /// <summary> /// 分隔符(默认为(,),也可以是其他分隔符如(\t)) /// </summary> public char SeparatorChar { get ; set ; } /// <summary> /// 标题所在行位置(默认为0,没有标题填-1) /// </summary> public int TitleRawIndex { get ; set ; } } } |
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 | using StockCheckApp.Utils; using System; using System.Collections.Generic; using System.Text; using System.Xml.Linq; namespace StockCheckApp.Models { public class GoodsCheckInfo { /// <summary> /// 指示当前对象自创建以来,属性 GoodsCode 是否已经设置了值(含设置为 null)。 /// </summary> protected bool _isGoodsCodeSetValue; private string _goodsCode; /// <summary> /// 商品代码 /// </summary> [CsvColumn(Title = "商品代码" , TitleIndex = 0, OutputFormat = "" )] public string GoodsCode { get { return this ._goodsCode; } set { this ._goodsCode = value; this ._isGoodsCodeSetValue = true ; } } /// <summary> /// 指示当前对象自创建以来,属性 LotNo 是否已经设置了值(含设置为 null)。 /// </summary> protected bool _isLotNoSetValue; private string _lotNo; /// <summary> /// 批号 /// </summary> [CsvColumn(Title = "批号" , TitleIndex = 1, OutputFormat = "" )] public string LotNo { get { return this ._lotNo; } set { this ._lotNo = value; this ._isLotNoSetValue = true ; } } /// <summary> /// 指示当前对象自创建以来,属性 GoodsQty 是否已经设置了值(含设置为 null)。 /// </summary> protected bool _isGoodsQtySetValue; private string _goodsQty; /// <summary> /// 盘点数量 /// </summary> [CsvColumn(Title = "盘点数量" , TitleIndex = 2, OutputFormat = "" )] public string GoodsQty { get { return this ._goodsQty; } set { this ._goodsQty = value; this ._isGoodsQtySetValue = true ; } } public bool UpdateTag { get ; set ; } } } using StockCheckApp.Utils; using System; using System.Collections.Generic; using System.Text; using System.Xml.Linq; namespace StockCheckApp.Models { public class GoodsInfo { /// <summary> /// 指示当前对象自创建以来,属性 GoodsCode 是否已经设置了值(含设置为 null)。 /// </summary> protected bool _isGoodsCodeSetValue; private string _goodsCode; /// <summary> /// 商品编号 /// </summary> [CsvColumn(Title = "商品代码" , TitleIndex = 0, OutputFormat = "" )] public string GoodsCode { get { return this ._goodsCode; } set { this ._goodsCode = value; this ._isGoodsCodeSetValue = true ; } } /// <summary> /// 指示当前对象自创建以来,属性 BarCode1 是否已经设置了值(含设置为 null)。 /// </summary> protected bool _isBarCode1SetValue; private string _barCode1; /// <summary> /// 商品条码1 /// </summary> [CsvColumn(Title = "条码1" , TitleIndex = 1, OutputFormat = "" )] public string BarCode1 { get { return this ._barCode1; } set { this ._barCode1 = value; this ._isBarCode1SetValue = true ; } } /// <summary> /// 指示当前对象自创建以来,属性 BarCode2 是否已经设置了值(含设置为 null)。 /// </summary> protected bool _isBarCode2SetValue; private string _barCode2; /// <summary> /// 商品条码2 /// </summary> [CsvColumn(Title = "条码2" , TitleIndex = 2, OutputFormat = "" )] public string BarCode2 { get { return this ._barCode2; } set { this ._barCode2 = value; this ._isBarCode2SetValue = true ; } } /// <summary> /// 指示当前对象自创建以来,属性 BarCode3 是否已经设置了值(含设置为 null)。 /// </summary> protected bool _isBarCode3SetValue; private string _barCode3; /// <summary> /// 商品条码3 /// </summary> [CsvColumn(Title = "条码3" , TitleIndex = 3, OutputFormat = "" )] public string BarCode3 { get { return this ._barCode3; } set { this ._barCode3 = value; this ._isBarCode3SetValue = true ; } } /// <summary> /// 指示当前对象自创建以来,属性 BarCode4 是否已经设置了值(含设置为 null)。 /// </summary> protected bool _isBarCode4SetValue; private string _barCode4; /// <summary> /// 商品条码4 /// </summary> [CsvColumn(Title = "条码4" , TitleIndex = 4, OutputFormat = "" )] public string BarCode4 { get { return this ._barCode4; } set { this ._barCode4 = value; this ._isBarCode4SetValue = true ; } } /// <summary> /// 指示当前对象自创建以来,属性 BarCode5 是否已经设置了值(含设置为 null)。 /// </summary> protected bool _isBarCode5SetValue; private string _barCode5; /// <summary> /// 商品条码5 /// </summary> [CsvColumn(Title = "条码5" , TitleIndex = 5, OutputFormat = "" )] public string BarCode5 { get { return this ._barCode5; } set { this ._barCode5 = value; this ._isBarCode5SetValue = true ; } } /// <summary> /// 指示当前对象自创建以来,属性 GoodsName 是否已经设置了值(含设置为 null)。 /// </summary> protected bool _isGoodsNameSetValue; private string _goodsName; /// <summary> /// 商品名称(中文) /// </summary> [CsvColumn(Title = "商品名称" , TitleIndex = 6, OutputFormat = "" )] public string GoodsName { get { return this ._goodsName; } set { this ._goodsName = value; this ._isGoodsNameSetValue = true ; } } } } |
使用:
string dirGoodsMst = Directory.GetCurrentDirectory() + "\\DataResource\\GoodsMst.csv";
List<GoodsInfo> GoodsInfos = CsvHelper.getInstance().Read<GoodsInfo>(dirGoodsMst, csvFileDescription);
/// <summary> /// 反序列化固定字符串格式 属性用\t间隔,行用\n间隔 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="data"></param> /// <returns></returns> public static List<T> DeserializeFromString<T>(string data, bool exceptHeader) { //类型T的所有属性 Dictionary<int, FieldMapper> fieldMapperDic = FieldMapper.GetModelFieldMapper<T>().ToDictionary(m => m.ColumnIndex); List<T> list = new(); var targetType = typeof(T); var dataString = data.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); if (exceptHeader && dataString.Length > 0) { dataString = dataString.Remove(dataString[0]); } foreach (var item in dataString) { //创建新对象 T t = (T)Activator.CreateInstance(targetType); //对象值列表 var stockCheckItemStrArray = item.Split(new string[] { "\t" }, StringSplitOptions.None); //数据长度和字段长度比对,哪个短,以哪个为准。超出的不予赋值。避免报错。 int dataCount = stockCheckItemStrArray.Length; if (stockCheckItemStrArray.Length > fieldMapperDic.Count) { //throw new Exception("数据长度" + stockCheckItemStrArray.Length + ",超出字段长度" + fieldMapperDic.Count + ":" + item); dataCount = fieldMapperDic.Count; string msgWrite = "targetType:" + targetType + ",数据长度" + stockCheckItemStrArray.Length + ",超出字段长度" + fieldMapperDic.Count + ":" + item; AppTraceLog.WriteInfo(msgWrite); } //循环为对象属性赋值 for (int i = 0; i < dataCount; i++) { string proName = fieldMapperDic[i].PropertyInfo.Name; string proValue = stockCheckItemStrArray[i]; PropertyInfo pit = targetType.GetProperty(proName); pit.SetValue(t, proValue, null); } //保存到集合中 list.Add(t); } return list; } /// <summary> /// 反序列化固定字符串格式 属性用\t间隔,行用\n间隔 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="data"></param> /// <returns></returns> public static List<T> DeserializeFromCompressString<T>(string data, bool exceptHeader) { //解压缩字符串 string decompressStr = StringCompress.DecompressString(data); var res = DeserializeFromString<T>(decompressStr, exceptHeader); return res; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2021-09-29 .net core发布到iis
2016-09-29 sql拼接一列数据