//加载二维曲线,就是二维偏差曲线 private static string Load2DConfig(string path, string filepre, DateTime readdate, ref List <PSLCalcu.Module.Curve2D> curves) { string readStatus = ""; int i, j, k; //首先寻找合适的文件 FileSystemInfo info; info = new DirectoryInfo(path); //查询路径文件夹是否存在 if (!info.Exists) //路径文件夹不存在,返回空的curve { curves = null; readStatus = readStatus + Environment.NewLine + String.Format("路径文件夹{0}不存在!", path); return(readStatus); } else { readStatus = readStatus + Environment.NewLine + String.Format("路径文件夹{0}存在!", path); } DirectoryInfo dir = info as DirectoryInfo; //如果路径文件夹存在,则获取文件夹对象 if (dir == null) //如果路径文件夹对象为空,则返回空的curve { curves = null; readStatus = readStatus + Environment.NewLine + String.Format("路径文件夹中没有任何文件!"); return(readStatus); } List <string> filenames = new List <string>(); //记录所有符合条件的文件名 readStatus = readStatus + Environment.NewLine + String.Format("在文件夹{0}中寻找符合条件的配置文件!", path); FileSystemInfo[] files = dir.GetFileSystemInfos(); //获取路径文件夹下所有文件 bool findflag = false; for (i = 0; i < files.Length; i++) { try { readStatus = readStatus + Environment.NewLine + String.Format("——解析文件名{0}!", files[i].Name); if (filepre.ToUpper() == "BIASCURVE_2D") { string[] fields = new string[6]; //文件名称必须由6部分构成,如BiasCurve_2D_CurveName_2_2018-01-01_0200.csv fields = files[i].Name.Split('_'); string curvetype = fields[0].ToUpper(); //曲线类型 string curvedime = fields[1].ToUpper(); //曲线维度 string curvename = fields[2]; //曲线名称 int curveindex = int.Parse(fields[3]); //曲线序号 DateTime filedate = DateTime.Parse(fields[4] + " " + fields[5].Substring(0, 2) + ":" + fields[5].Substring(2, 2)); //曲线时间 string filetype = fields[5].Split('.')[1].ToUpper(); //文件类型 if (filetype == "CSV" && //必须是CSV文件 (curvetype + "_" + curvedime) == filepre.ToUpper() //文件名前缀必须是filepre,这里是BiasCurve_2D ) //filedate < readdate) //必须比当前读取时间早 { filenames.Add(files[i].Name); findflag = true; } } else if (filepre.ToUpper() == "SCORECURVE_2D") { string[] fields = new string[6]; //文件名称必须由6部分构成,如BiasCurve_2D_CurveName_2_2018-01-01_0200.csv fields = files[i].Name.Split('_'); string curvetype = fields[0].ToUpper(); //曲线类型 string curvedime = fields[1].ToUpper(); //曲线维度 string curvename = fields[2]; //曲线名称 int curveindex = int.Parse(fields[3]); //曲线序号 DateTime filedate = DateTime.Parse(fields[4] + " " + fields[5].Substring(0, 2) + ":" + fields[5].Substring(2, 2)); //曲线时间 string filetype = fields[5].Split('.')[1].ToUpper(); //文件类型 if (filetype == "CSV" && //必须是CSV文件 (curvetype + "_" + curvedime) == filepre.ToUpper() //文件名前缀必须是filepre,这里是BiasCurve_2D ) //filedate < readdate) //必须比当前读取时间早 { filenames.Add(files[i].Name); findflag = true; } } } catch (Exception ex) { readStatus = readStatus + Environment.NewLine + String.Format("————文件名称解析错误!"); continue; //文件格式有误,直接下一个文件夹 } } if (findflag == false) { curves = null; readStatus = readStatus + Environment.NewLine + String.Format("路径文件夹{0}中没有找到文件名前缀和有效时间均符合条件的曲线配置文件!", path); return(readStatus); } else { readStatus = readStatus + Environment.NewLine + String.Format("路径文件夹{0}已经找到文件名前缀和有效时间均符合条件的曲线配置文件!", path); } //从找到的文件中读取数据 bool readflag = false; for (int ifiles = 0; ifiles < filenames.Count; ifiles++) { string filename = path + filenames[ifiles]; string[] fields = filenames[ifiles].Split('_'); DateTime filedate = DateTime.Parse(fields[4] + " " + fields[5].Substring(0, 2) + ":" + fields[5].Substring(2, 2)); //曲线时间。//文件名称必须由6部分构成,如BiasCurve_2D_CurveName_2_2018-01-01_0200.csv //开始解析文件,读取Curve2D对象 //——假设files是已经选取好的所有2D文件 //——无论动态读取还是静态读取,任何时候发生错误,将返回null。 //——偏差算法中,在使用前先判断是否为null。如果为空,偏差算法会报曲线错误。 PSLCalcu.Module.Curve2D cur = new PSLCalcu.Module.Curve2D(); string[][] filedata; try { filedata = CsvFileReaderForModule.Read(filename); readStatus = readStatus + Environment.NewLine + String.Format("——解析配置文件{0}的数据!", filename); cur.Name = filedata[0][0].Substring(1, filedata[0][0].Length - 2); //第1行,第一个单元格是[曲线名称] cur.Index = int.Parse(filedata[0][1]); //第1行,第二个单元个是曲线序号 cur.validDate = filedate; //有效时间 cur.XLowerLimit = double.Parse(filedata[0][2].Trim()); //第1行,第三个单元格是自变量X的下限 cur.XUpperLimit = double.Parse(filedata[0][3].Trim()); //第1行,第四个单元格是自变量X的上限 cur.YLowerLimit = double.Parse(filedata[0][4].Trim()); //第1行,第五个单元格是自变量Y的下限 cur.YUpperLimit = double.Parse(filedata[0][5].Trim()); //第1行,第六个单元格是自变量Y的上限 cur.Mode = filedata[0][6].Trim().ToUpper(); //第1行,第七个单元格是曲线模式 if (cur.Mode != "FUNCTION" && cur.Mode != "TABLE") { readStatus = readStatus + Environment.NewLine + String.Format("————配置模式参数不正确!模式参数必须是'FUNCTION'或'TABLE'"); //curves.Add(null);//参数不正确不能加入null,否则后面读取曲线时,curves中有空对象,会报错 continue; } else { readStatus = readStatus + Environment.NewLine + String.Format("————配置模式为{0}", cur.Mode); } int _rowcount = filedata.Length; int _colcount = filedata[1].Length; //第1行,是X //读Table模式下,表的X和Y //填充Xvalue cur.Xvalue = new double[_colcount - 1]; for (i = 1; i < _colcount; i++) { if (filedata[1][i] != "") { cur.Xvalue[i - 1] = double.Parse(filedata[1][i]); } else { //遇到空字符,停止读取,重新截取数组长度。注意这里必须截取。偏差计算和得分计算,都要使用边界数据。 cur.Xvalue = cur.Xvalue.Take(i - 1).ToArray(); } } readStatus = readStatus + Environment.NewLine + String.Format("————X读取完毕"); //填充Yvalue //第0列,是Y cur.Yvalue = new double[_rowcount - 2]; cur.Ztable = new double[_rowcount - 2][]; for (i = 2; i < _rowcount; i++) { if (filedata[i][0] != "") { cur.Yvalue[i - 2] = double.Parse(filedata[i][0]); cur.Ztable[i - 2] = new double[cur.Xvalue.Length]; } } readStatus = readStatus + Environment.NewLine + String.Format("————“Y读取完毕"); //填充Ztable for (i = 2; i < _rowcount; i++) { for (j = 1; j < _colcount; j++) { if (filedata[i][j] != "") { cur.Ztable[i - 2][j - 1] = double.Parse(filedata[i][j]); } } } readStatus = readStatus + Environment.NewLine + String.Format("————Z读取完毕"); //修正上下限 //要注意,防止偏差曲线的x不是从小到大。(但是,目前硬性要求期望曲线和得分曲线配置,范围要从低到高。因此老版本上,没有这个判断) double xmin = cur.Xvalue[0] < cur.Xvalue[cur.Xvalue.Length - 1] ? cur.Xvalue[0] : cur.Xvalue[cur.Xvalue.Length - 1]; double xmax = cur.Xvalue[cur.Xvalue.Length - 1] > cur.Xvalue[0] ? cur.Xvalue[cur.Xvalue.Length - 1] : cur.Xvalue[0]; if (cur.XLowerLimit < xmin) { cur.XLowerLimit = xmin; //必须保证有效考核范围[XLowerLimit,XUpperLimit]范围要小于或等于cur.Xvalue范围。 } if (cur.XUpperLimit > xmax) { cur.XUpperLimit = xmax; } double ymin = cur.Yvalue[0] < cur.Yvalue[cur.Yvalue.Length - 1] ? cur.Yvalue[0] : cur.Yvalue[cur.Yvalue.Length - 1]; double ymax = cur.Yvalue[cur.Yvalue.Length - 1] > cur.Yvalue[0] ? cur.Yvalue[cur.Yvalue.Length - 1] : cur.Yvalue[0]; if (cur.YLowerLimit < ymin) { cur.YLowerLimit = ymin; //必须保证有效考核范围[XLowerLimit,XUpperLimit]范围要小于或等于cur.Xvalue范围。 } if (cur.YUpperLimit > ymax) { cur.YUpperLimit = ymax; } //读Function模式下,A,B,C,从第0行,第1列开始 if (cur.Mode == "FUNCTION") { cur.A1 = double.Parse(filedata[0][7].Trim()); //第0行,第8个单元格是Funtion模式下的拟合参数A cur.B1 = double.Parse(filedata[0][8].Trim()); //第0行,第9个单元格是Funtion模式下的拟合参数B cur.A2 = double.Parse(filedata[0][9].Trim()); //第0行,第10个单元格是Funtion模式下的拟合参数A cur.B2 = double.Parse(filedata[0][10].Trim()); //第0行,第11个单元格是Funtion模式下的拟合参数B cur.C = double.Parse(filedata[0][11].Trim()); //第0行,第12个单元格是Funtion模式下的拟合参数C } readStatus = readStatus + Environment.NewLine + String.Format("————参数A1B1A2B2C读取完毕"); curves.Add(cur); readStatus = readStatus + Environment.NewLine + String.Format("——添加曲线{0}", cur.Name); readflag = true; } catch (Exception ex) { //String msgStr = String.Format("初始化二维偏差曲线时出错!请检查..."); //MessageBox.Show(msgStr); //ErrorFlag = true; //ErrorInfo = ex.ToString(); //return null; //无论动态读取还是静态读取,任何时候发生错误,将返回null。 //偏差算法中,在使用前先判断是否为null。如果为空,偏差算法会报曲线错误。 readStatus = readStatus + Environment.NewLine + String.Format("——文件数据解析错误!详细信息:{0}", ex.ToString()); //curves.Add(null);//参数不正确不能加入null,否则后面读取曲线时,curves中有空对象,会报错 continue; } }//end for 遍历文件 if (curves.Count != 0 && readflag == true) { readStatus = readStatus + String.Format("配置曲线读取完毕!"); //如果一切读取顺利,则readStatus前面的记录均不记录。直接赋予最后的值。 return(readStatus); } else { curves = null; readStatus = readStatus + Environment.NewLine + readStatus + String.Format("在配置文件内没有读取到任何有效的曲线配置数据!"); return(readStatus); } }
public static Results Calcu(List <PValue>[] inputs, CalcuInfo calcuinfo) { //对于MReadConst算法: //——不需要源标签,因此源标签填写任何一个rdb标签即可,源标签类型填写const //——读取数据阶段,遇到const,直接置input[0]=null,计算引擎不记报警和错误,直接跳转 //公用变量 bool _errorFlag = false; string _errorInfo = ""; bool _warningFlag = false; string _warningInfo = ""; bool _fatalFlag = false; string _fatalInfo = ""; int i; List <PValue>[] results; try { //0、参数。读取的常量配置文件名称 //string configfilename = String.Parse(calcuinfo.fparas); string[][] csvdata = null; string filename = ""; string filefullpath = ""; //1、常量配置文件遍历 string csvFilePath = System.Environment.CurrentDirectory + "\\ConstConfig\\"; DirectoryInfo tagfolder = new DirectoryInfo(csvFilePath); FileInfo[] tagfiles = tagfolder.GetFiles("constconfig*.csv", SearchOption.TopDirectoryOnly); //2、在常数配置文件夹中找格式符合的文件,并获得文件时间参数, Dictionary <DateTime, string> filevaliddateDic = new Dictionary <DateTime, string>(); for (i = 0; i < tagfiles.Length; i++) { filename = tagfiles[i].ToString(); //对文件名称进行解析,文件名称格式:constconfig_2018-01-01_0800.csv string[] filenames = filename.Split('_'); //用_分割 if (filenames.Length < 3) { continue; //如果少于三部分则不对,看下一个文件名 } DateTime filevaliddate = new DateTime(); try { filevaliddate = DateTime.Parse(filenames[1] + " " + filenames[2].Substring(0, 2) + ":" + filenames[2].Substring(2, 2)); //用第二部分构成时间 filevaliddateDic.Add(filevaliddate, filename); } catch { continue; } } //如果没有找到任何文件,就直接退出。并且错误报警。因为一个项目必须有正确的尝试配置文件 if (filevaliddateDic.Count == 0) { //找不到任何文件,要报错,并退出 _errorFlag = true; _errorInfo = "在\\ConstConfig文件夹下找不到符合条件的常数配置文件!"; return(new Results(null, _errorFlag, _errorInfo, _warningFlag, _warningInfo, _fatalFlag, _fatalInfo)); //这里退出,在计算引擎出会记录报错 } //3、找到时间上最后的文件 //生效时间有在当前计算周期前一个小时的文件时,进行读取 //找到文件要看最后一个时间是不是符合要求 filevaliddateDic = filevaliddateDic.OrderBy(m => m.Key).ToDictionary(pair => pair.Key, pair => pair.Value); //按时间顺序升序排列 foreach (var item in filevaliddateDic) { //3.1 依次获取每一个时间 DateTime filevaliddate = item.Key; //3.2 找到符合时间范围的那个文件:1、文档有效日期在当前计算结束日期之前。2、文档日期在当前计算时间之前2个小时以内(避免每次都读,仅在这两个小时内读取) if (filevaliddate < calcuinfo.fendtime && calcuinfo.fendtime.Subtract(filevaliddate).TotalHours <= 2 && calcuinfo.fendtime.Subtract(filevaliddate).TotalHours > 0) { //3.2.1将该文件的常数值读取出来 filename = item.Value; //取时间对应的文件名称 filefullpath = csvFilePath + filename; csvdata = CsvFileReaderForModule.Read(filefullpath); if (csvdata == null || csvdata.Length == 0) { //说明相应文件内没有符合条件的数据,要给出报警 //如果不符合要求,则说明当前没有需要更新的常数文件,正常退出 _errorFlag = true; _errorInfo = "在" + filefullpath + "文件中没有找到有效数据!"; return(new Results(null, _errorFlag, _errorInfo, _warningFlag, _warningInfo, _fatalFlag, _fatalInfo)); //这里退出,在计算引擎出会记录报错 } //3.2.2 如果静态参数输出数量OutputNumberStatic,还没有被初始化,则必须先进行一次初始化。 //这是一个静态变量,程序启动后,仅执行一次。 if (OutputNumberStatic == 0) //只要OutputNumberStatic为0,就说明未被初始化,因为只要配置了常数读取算法,就一定有常数项 { OutputNumberStatic = csvdata.Length - 1; } //3.2.3 读取常数标签的值,并组织计算结果 //特别注意,结果中,常数标签值得时间戳timestamp,不是用calcuinfo的起始时间,而是用文件名的时间。 results = new List <PValue> [OutputNumberStatic]; for (i = 1; i < csvdata.Length; i++) { results[i - 1] = new List <PValue>(); results[i - 1].Add(new PValue(double.Parse(csvdata[i][4]), filevaliddate, calcuinfo.fendtime, 0)); //要保证写入的点在当前时间段内,这些计算引擎写入结果时才不会出错。 } return(new Results(results, _errorFlag, _errorInfo, _warningFlag, _warningInfo, _fatalFlag, _fatalInfo)); } //end if 符合时间范围 } //end foreach //如果循环体内没有找到适合时间内的文件,则不会在循环体内退出 //这种找不到适合文件的情况属于正常情况 //返回一个总体为空的结果,计算主引擎,对MReadShift和MReadConst的计算结果整体为null,不会报错。 results = null; //在完成new List<PValue>[OutputNumberStatic]之后, results恰好是一个长度为OutputNumberStatic,每个元素为null的数组。 return(new Results(results, _errorFlag, _errorInfo, _warningFlag, _warningInfo, _fatalFlag, _fatalInfo)); } catch (Exception ex) { //计算中出任何错误,则需要记录log //LogHelper.Write(LogType.Error, "计算模块错误!"); //记录计算模块的名称、当前标签、起始时间、结束时间 //string moduleInfo = string.Format("——计算模块的名称是:{0},当前计算源标签是:{1},计算起始时间是:{2},计算结束时间是:{3}。", calcuInfo.fmodulename, calcuInfo.sourcetagname, calcuinfo.fstarttime.ToString(), calcuinfo.fendtime.ToString()); //LogHelper.Write(LogType.Error, moduleInfo); //计算引擎报错具体信息 //string errInfo = string.Format("——具体报错信息:{0}。", ex.ToString()); //LogHelper.Write(LogType.Error, errInfo); //返回null供计算引擎处理 _fatalFlag = true; _fatalInfo = "读取值常数配置表\\ConstConfig\\constconfig.csv错误!" + ex.ToString(); return(new Results(null, _errorFlag, _errorInfo, _warningFlag, _warningInfo, _fatalFlag, _fatalInfo)); } }
//***************用动态方式获得偏差曲线和得分曲线************************************ //——在算法每次被调用时,都从CSV读取一次配置文件 //——在算法中的调用方式为Curve1D opxCurve = CurveConfig.ReadOPXCurves.Find(delegate(Curve1D a) { return a.Index == opxid; }); //——20181031,因动态方式读取曲线,速度太慢,不在采用。 //——转而采用在静态方式下读取带生效时间的配置曲线。这样在增加配置曲线时,仅需要暂停计算引擎后重启,即可载入新的配置曲线,并继续进行计算。 /* * public static List<PSLCalcu.Module.Curve1D> ReadOPXCurves(DateTime readdate) * { * //读取一维偏差期望曲线 * string filePath = Environment.CurrentDirectory + "\\" + ConfigPath + "\\"; * string fileNamePre = DEV1DCURVE_FILE; * List<Curve1D> curvesOPX = new List<Curve1D>(); * Load1DConfig(filePath, fileNamePre, readdate, ref curvesOPX); * * return curvesOPX; * } * public static List<PSLCalcu.Module.Curve2D> ReadOPXCurves2D(DateTime readdate) * { * //读取二维偏差期望曲线 * string fileName = Environment.CurrentDirectory + "\\" + ConfigPath + "\\"; * string fileNamePre = DEV2DCURVE_FILE; * List<Curve2D> curvesOPX2D = new List<Curve2D>(); * Load2DConfig(fileName, fileNamePre, readdate, ref curvesOPX2D); * return curvesOPX2D; * } * public static List<PSLCalcu.Module.Curve1D> ReadScoreCurves(DateTime readdate) * { * //读取一维得分期望曲线 * string filePath = Environment.CurrentDirectory + "\\" + ConfigPath + "\\" ; * string fileNamePre = SCORECURVE_FILE; * List<Curve1D> curvesscore = new List<Curve1D>(); * Load1DConfig(filePath, fileNamePre, readdate, ref curvesscore); * return curvesscore; * } */ #region 静态加载和动态加载两种方式的公用载入方法 //加载一维曲线文件,包括一维偏差曲线和得分曲线 private static string Load1DConfig(string path, string filepre, DateTime readdate, ref List <PSLCalcu.Module.Curve1D> curves) { string readStatus = ""; int i, j; //首先寻找合适的文件 FileSystemInfo info; info = new DirectoryInfo(path); //查询路径文件夹是否存在 if (!info.Exists) //路径文件夹不存在,返回空的curve { curves = null; readStatus = readStatus + Environment.NewLine + String.Format("路径文件夹{0}不存在!", path); return(readStatus); } else { readStatus = readStatus + Environment.NewLine + String.Format("路径文件夹{0}存在!", path); } DirectoryInfo dir = info as DirectoryInfo; //如果路径文件夹存在,则获取文件夹对象 if (dir == null) //如果路径文件夹对象为null,则返回空的curve { curves = null; readStatus = readStatus + Environment.NewLine + String.Format("路径文件夹{0}中没有任何文件!", path); return(readStatus); } readStatus = readStatus + Environment.NewLine + String.Format("在文件夹{0}中寻找符合条件的配置文件!", path); FileSystemInfo[] files = dir.GetFileSystemInfos(); //获取路径文件夹下所有文件 List <string> filenames = new List <string>(); //记录所有符合条件的文件名 bool findflag = false; //找到标记 for (i = 0; i < files.Length; i++) //对文件夹下所有文件进行遍历,找到文件名称中符合条件的文件名称 { try { readStatus = readStatus + Environment.NewLine + String.Format("——解析文件名{0}!", files[i].Name); if (filepre.ToUpper() == "BIASCURVE_1D") { string[] fields = new string[3]; //文件名称必须由3部分构成,如BiasCurve_1D_2018-05-06_0200.csv。files[0]是曲线类别,files[1]曲线维度,files[2]曲线有效时间 fields = files[i].Name.Split('_'); string curvetype = fields[0].ToUpper(); //曲线类型 string curvedime = fields[1].ToUpper(); //曲线维度 DateTime filedate = DateTime.Parse(fields[2] + " " + fields[3].Substring(0, 2) + ":" + fields[3].Substring(2, 2)); //曲线时间 string filetype = fields[3].Split('.')[1]; if (filetype.ToUpper() == "CSV" && //必须是csv文件 (curvetype.ToUpper() + "_" + curvedime.ToUpper()) == filepre.ToUpper() //必须是filepre文件,即BIASCURVE_1D ) //filedate < readdate) //必须是曲线时间小于当前读取时间。20181101去掉该条件 { filenames.Add(files[i].Name); findflag = true; } } else if (filepre.ToUpper() == "SCORECURVE") { string[] fields = new string[3]; //文件名称必须由3部分构成,如BiasCurve_1D_2018-05-06_0200.csv fields = files[i].Name.Split('_'); string curvetype = fields[0].ToUpper(); //曲线类型 //string curvedime = fields[1].ToUpper(); //曲线维度 DateTime filedate = DateTime.Parse(fields[1] + " " + fields[2].Substring(0, 2) + ":" + fields[2].Substring(2, 2)); //曲线时间 string filetype = fields[2].Split('.')[1]; if (filetype.ToUpper() == "CSV" && //必须是csv文件 curvetype.ToUpper() == filepre.ToUpper() //必须是filepre文件,即SCORECURVE ) //filedate < readdate) //时间必须小于当前读取时间.20181101去掉该条件 { filenames.Add(files[i].Name); findflag = true; } } } catch (Exception ex) { readStatus = readStatus + Environment.NewLine + String.Format("————文件名称解析错误!"); continue; //文件格式有误,直接下一个文件夹 } } if (findflag == false) { curves = null; readStatus = readStatus + Environment.NewLine + String.Format("路径文件夹{0}中没有找到文件名前缀和有效时间均符合条件的曲线配置文件!", path); return(readStatus); } else { readStatus = readStatus + Environment.NewLine + String.Format("路径文件夹{0}中已经找到文件名前缀和有效时间均符合条件的曲线配置文件!", path); } //从找到的文件中读取数据 bool readflag = false; for (int ifiles = 0; ifiles < filenames.Count; ifiles++) { string filename = path + filenames[ifiles]; string[] fields = filenames[ifiles].Split('_'); DateTime filedate = new DateTime(); if (fields[0].Trim().ToUpper() + "_" + fields[1].Trim().ToUpper() == "BIASCURVE_1D") //这里选出的一定是BIASCURVE_1D为前缀的文件 { filedate = DateTime.Parse(fields[2] + " " + fields[3].Substring(0, 2) + ":" + fields[3].Substring(2, 2)); //曲线时间 } else if (fields[0].Trim().ToUpper() == "SCORECURVE") { filedate = DateTime.Parse(fields[1] + " " + fields[2].Substring(0, 2) + ":" + fields[2].Substring(2, 2)); //曲线时间 } //开始解析文件,读取Curve1D对象 //——无论动态读取还是静态读取,任何时候发生错误,将返回null。 //——偏差算法中,在使用前先判断是否为null。如果为空,偏差算法会报曲线错误。 PSLCalcu.Module.Curve1D cur; readStatus = readStatus + Environment.NewLine + String.Format("解析配置文件{0}中的数据!", filename); string[][] filedata = CsvFileReaderForModule.Read(filename); for (i = 0; i < filedata.Length; i++) { try { if (filedata[i][0].Substring(0, 1) == "[") //数据是逐行扫描的,当遇到改行第一个单元格是以'['开头,则表明这是一个曲线配置的起始位置 { cur = new PSLCalcu.Module.Curve1D(); cur.Name = filedata[i][0].Substring(1, filedata[i][0].Length - 2); //第1行,第一个单元格是[曲线名称] cur.Index = int.Parse(filedata[i][1]); //第1行,第二个单元个是曲线序号 cur.validDate = filedate; //曲线有效时间 //Console.WriteLine("content:"+filedata[i][2].Trim()); cur.XLowerLimit = double.Parse(filedata[i][2].Trim()); //第1行,第三个单元格是自变量X的下限 cur.XUpperLimit = double.Parse(filedata[i][3].Trim()); //第1行,第四个单元格是自变量X的上限 cur.Mode = filedata[i][4].Trim().ToUpper(); //第1行,第五个单元格是曲线配置模式。是数据表型Table,还是函数型Function if (cur.Mode != "FUNCTION" && cur.Mode != "TABLE") { readStatus = readStatus + Environment.NewLine + String.Format("——配置模式参数不正确!模式参数必须是'FUNCTION'或'TABLE'"); //curves.Add(null); //参数不正确不能加入null,否则后面读取曲线时,curves中有空对象,会报错 i = i + 2; continue; } else { readStatus = readStatus + Environment.NewLine + String.Format("————配置模式为{0}", cur.Mode); } //读Table模式下,表的X和Y //——无论Table模式,或者Function模式,都要读Table。 //——Table模式,需要用Table来判断有效边界,并计算 //——Function模式,需要用Table来判断边界。 cur.Xvalue = new double[filedata[i + 1].Length]; cur.Yvalue = new double[filedata[i + 1].Length]; for (j = 0; j < filedata[i + 1].Length; j++) { if (filedata[i + 1][j].Trim() != "" && filedata[i + 2][j].Trim() != "") { cur.Xvalue[j] = double.Parse(filedata[i + 1][j].Trim()); cur.Yvalue[j] = double.Parse(filedata[i + 2][j].Trim()); } else { //遇到空字符,停止读取,重新截取数组长度。注意这里必须截取。偏差计算和得分计算,都要使用边界数据。 cur.Xvalue = cur.Xvalue.Take(j).ToArray(); cur.Yvalue = cur.Yvalue.Take(j).ToArray(); } } //修正上下限 //修正上下限 //要注意,防止偏差曲线的x不是从小到大。(但是,目前硬性要求期望曲线和得分曲线配置,范围要从低到高。因此老版本上,没有这个判断) double xmin = cur.Xvalue[0] < cur.Xvalue[cur.Xvalue.Length - 1] ? cur.Xvalue[0] : cur.Xvalue[cur.Xvalue.Length - 1]; double xmax = cur.Xvalue[cur.Xvalue.Length - 1] > cur.Xvalue[0] ? cur.Xvalue[cur.Xvalue.Length - 1] : cur.Xvalue[0]; if (cur.XLowerLimit < xmin) { cur.XLowerLimit = xmin; //必须保证有效考核范围[XLowerLimit,XUpperLimit]范围要小于或等于cur.Xvalue范围。 } if (cur.XUpperLimit > xmax) { cur.XUpperLimit = xmax; } readStatus = readStatus + Environment.NewLine + String.Format("——X和Y读取完毕"); //读Function模式下,A,B,C if (cur.Mode == "FUNCTION") { cur.A = double.Parse(filedata[i][5].Trim()); //第1行,第6个单元格是Funtion模式下的拟合参数A cur.B = double.Parse(filedata[i][6].Trim()); //第1行,第7个单元格是Funtion模式下的拟合参数B cur.C = double.Parse(filedata[i][7].Trim()); //第1行,第8个单元格是Funtion模式下的拟合参数B } readStatus = readStatus + Environment.NewLine + String.Format("——参数ABC读取完毕"); curves.Add(cur); readStatus = readStatus + Environment.NewLine + String.Format("——添加曲线{0}", cur.Name); readflag = true; i = i + 2; } } catch (Exception ex) { //String msgStr = String.Format("初始化一维偏差/得分曲线时出错!请检查"); //MessageBox.Show(msgStr); //ErrorFlag = true; //ErrorInfo = ex.ToString(); //return null; //无论动态读取还是静态读取,任何时候发生错误,将返回null。 //偏差算法中,在使用前先判断是否为null。如果为空,偏差算法会报曲线错误。 readStatus = readStatus + Environment.NewLine + String.Format("——文件数据解析错误!详细信息:{0}", ex.ToString()); //curves.Add(null);//参数不正确不能加入null,否则后面读取曲线时,curves中有空对象,会报错 } } //end for 遍历数据 } //end for 遍历文件 if (readflag) { readStatus = readStatus + String.Format("配置曲线读取完毕!"); return(readStatus); } else { readStatus = readStatus + Environment.NewLine + String.Format("在文件中没有读取到任何有效的曲线配置数据!"); return(readStatus); } }