|
@@ -0,0 +1,572 @@
|
|
|
|
+package com.cpp.web.service.cloud;
|
|
|
|
+
|
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
|
+import cn.hutool.core.util.NumberUtil;
|
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
|
+import cn.hutool.core.util.RuntimeUtil;
|
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
|
+import cn.hutool.extra.ftp.Ftp;
|
|
|
|
+import cn.hutool.extra.ftp.FtpConfig;
|
|
|
|
+import cn.hutool.extra.ftp.FtpMode;
|
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
|
+import com.cpp.common.utils.StringUtils;
|
|
|
|
+import com.cpp.web.domain.AbnormalAlarm;
|
|
|
|
+import com.cpp.web.domain.cloud.ForecastPowerShortTermCloud;
|
|
|
|
+import com.cpp.web.domain.cloud.NwpCloud;
|
|
|
|
+import com.cpp.web.domain.datafactory.ParsingFileUrl;
|
|
|
|
+import com.cpp.web.domain.datafactory.ParsingLog;
|
|
|
|
+import com.cpp.web.domain.datafactory.ParsingType;
|
|
|
|
+import com.cpp.web.domain.datafactory.dto.ParsingResultDto;
|
|
|
|
+import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
|
|
|
|
+import com.cpp.web.domain.enums.AlarmEnum;
|
|
|
|
+import com.cpp.web.domain.enums.DataSourcesEnum;
|
|
|
|
+import com.cpp.web.mapper.datafactory.ParsingTypeMapper;
|
|
|
|
+import com.cpp.web.service.AbnormalAlarmService;
|
|
|
|
+import com.cpp.web.service.datafactory.ParsingFileUrlService;
|
|
|
|
+import com.cpp.web.service.datafactory.ParsingInterface;
|
|
|
|
+import com.cpp.web.service.datafactory.ParsingLogService;
|
|
|
|
+import com.cpp.web.utils.DateTimeUtil;
|
|
|
|
+import com.cpp.web.utils.MessageUtils;
|
|
|
|
+import com.cpp.web.utils.NumberUtils;
|
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
+import org.apache.commons.io.FileUtils;
|
|
|
|
+import org.apache.commons.lang3.time.DateFormatUtils;
|
|
|
|
+import org.springframework.scheduling.annotation.Scheduled;
|
|
|
|
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+
|
|
|
|
+import java.io.*;
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+import java.math.RoundingMode;
|
|
|
|
+import java.nio.charset.Charset;
|
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
|
+import java.nio.file.Files;
|
|
|
|
+import java.text.ParseException;
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
|
+import java.util.*;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * ftp文件解析
|
|
|
|
+ *
|
|
|
|
+ * @author tl
|
|
|
|
+ * @date 2022-05-11 09:51:21
|
|
|
|
+ */
|
|
|
|
+@AllArgsConstructor
|
|
|
|
+@Slf4j
|
|
|
|
+@Service
|
|
|
|
+public class CloudFileParsing {
|
|
|
|
+
|
|
|
|
+ private final ParsingLogService parsingLogService;
|
|
|
|
+
|
|
|
|
+ private final AbnormalAlarmService abnormalAlarmService;
|
|
|
|
+
|
|
|
|
+ private final ForecastPowerShortTermCloudService forecastPowerShortTermCloudService;
|
|
|
|
+ private final NwpCloudService nwpCloudService;
|
|
|
|
+
|
|
|
|
+ private final String PARSING_FILE_NEW_DIR = "/";
|
|
|
|
+
|
|
|
|
+ private final File fileNewDir = new File(PARSING_FILE_NEW_DIR);
|
|
|
|
+
|
|
|
|
+ private final ThreadPoolTaskExecutor executor;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 解析文件方法
|
|
|
|
+ * 逻辑:先配置识别文件名称类型:识别文件名称关键字对应的文件类型
|
|
|
|
+ * 有文件类型的配置才可以进入下一步
|
|
|
|
+ * <p>
|
|
|
|
+ * 查找各场站配置的ftp目录,去下载文件并识别文件类型执行对应的解析策略
|
|
|
|
+ * <p>
|
|
|
|
+ * 必要条件:1.配置文件识别类型。2.配置下载路径。3.配置解析公式
|
|
|
|
+ *
|
|
|
|
+ * @param
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ @Scheduled(fixedRate = 300000L)
|
|
|
|
+ public void parsingFile() {
|
|
|
|
+ {
|
|
|
|
+ log.info("-----------------开始执行预测文件解析任务----------------------");
|
|
|
|
+ Long currentDate = DateTimeUtil.getMillisecondsSubDay();//今日凌晨
|
|
|
|
+ boolean flag = false;
|
|
|
|
+
|
|
|
|
+ //判断该目录是否存在,不存在时创建
|
|
|
|
+ if (!fileNewDir.exists()) {
|
|
|
|
+ fileNewDir.mkdirs();
|
|
|
|
+ log.info("【" + fileNewDir.getPath() + "】目录不存在,系统自动创建文件目录");
|
|
|
|
+ }
|
|
|
|
+ log.info("系统扫描路径【" + fileNewDir.getPath() + "】");
|
|
|
|
+ // 获取指定目录下的文件
|
|
|
|
+ Collection<File> files = FileUtils.listFiles(fileNewDir, new String[]{"RB", "txt"}, false);
|
|
|
|
+ //当前时间格式化为年月日
|
|
|
|
+ String dayStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // 如果指定目录下有文件
|
|
|
|
+ if (files.size() > 0) {
|
|
|
|
+
|
|
|
|
+ List<ParsingLog> parsingLogs = new ArrayList<>();
|
|
|
|
+ List<AbnormalAlarm> abnormalAlarms = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+ // 循环文件并解析
|
|
|
|
+ for (File file : files) {
|
|
|
|
+ ParsingLog parsingLog = new ParsingLog();
|
|
|
|
+ flag = false;
|
|
|
|
+
|
|
|
|
+ String fileName = file.getName();
|
|
|
|
+
|
|
|
|
+ parsingLog.setDataSources(DataSourcesEnum.E2);
|
|
|
|
+ parsingLog.setParsingTime(new Date());
|
|
|
|
+ parsingLog.setFileName(fileName);
|
|
|
|
+
|
|
|
|
+ // 如果文件不是当然的,删除文件
|
|
|
|
+ if (!fileName.contains(dayStr)) {
|
|
|
|
+ file.delete();
|
|
|
|
+ log.warn(fileName + "不是当天的文件,删除!");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ // 如果文件名长度符合规则
|
|
|
|
+ if (fileName.length() < 30) {
|
|
|
|
+ // 如果是短期文件
|
|
|
|
+ if (file.getName().startsWith("DQ")) {
|
|
|
|
+ try {
|
|
|
|
+ parsingLog.setFileType(FileTypeEnum.dq);
|
|
|
|
+ // 解析短期文件
|
|
|
|
+ List<ForecastPowerShortTermCloud> listDq = fileAnalysisShortTerm(file, new Date(currentDate));
|
|
|
|
+ if (!listDq.isEmpty()) {
|
|
|
|
+ try {
|
|
|
|
+ parsingLog.setStationCode(listDq.get(0).getStationCode());
|
|
|
|
+ forecastPowerShortTermCloudService.saveBatch(listDq);
|
|
|
|
+ flag = true;
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("保存短期数据报错:"+fileName, e);
|
|
|
|
+ parsingLog.setParsingDescribe("保存短期数据报错:"+fileName);
|
|
|
|
+ flag = false;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ log.info(file.getName() + "文件数据内容为空、不能正常解析 、移除该文件:"+fileName);
|
|
|
|
+ parsingLog.setParsingDescribe("文件数据内容为空、不能正常解析 、移除该文件:"+fileName);
|
|
|
|
+ flag = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ flag = false;
|
|
|
|
+ parsingLog.setParsingDescribe("解析DQ文件异常:"+fileName);
|
|
|
|
+ log.error("解析DQ文件失败:"+fileName, e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (file.getName().startsWith("NWP")) {
|
|
|
|
+ try {
|
|
|
|
+ parsingLog.setFileType(FileTypeEnum.nwp);
|
|
|
|
+ List<NwpCloud> listNwp = fileAnalysisNwp(file,new Date(currentDate));
|
|
|
|
+ if (!listNwp.isEmpty()) {
|
|
|
|
+ try {
|
|
|
|
+ parsingLog.setStationCode(listNwp.get(0).getStationCode());
|
|
|
|
+ nwpCloudService.saveBatch(listNwp);
|
|
|
|
+ flag = true;
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("保存NWP数据报错:"+fileName, e);
|
|
|
|
+ parsingLog.setParsingDescribe("保存NWP数据报错:"+fileName);
|
|
|
|
+ flag = false;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ parsingLog.setParsingDescribe("文件数据内容为空、不能正常解析 、移除该文件:"+fileName);
|
|
|
|
+ log.info(file.getName() + "文件数据内容为空、不能正常解析 、移除该文件");
|
|
|
|
+ flag = false;
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("解析NWP文件失败:"+fileName, e);
|
|
|
|
+ parsingLog.setParsingDescribe("解析NWP文件失败:"+fileName);
|
|
|
|
+ flag = false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (flag) {
|
|
|
|
+ parsingLog.setParsingFileStatus("成功");
|
|
|
|
+ } else {
|
|
|
|
+ parsingLog.setParsingFileStatus("失败");
|
|
|
|
+ abnormalAlarms.add(new AbnormalAlarm(DataSourcesEnum.E2,AlarmEnum.E4,parsingLog.getParsingDescribe(),""));
|
|
|
|
+ //移除文件备份到error文件下
|
|
|
|
+ moveFileError(file);
|
|
|
|
+ }
|
|
|
|
+ parsingLogs.add(parsingLog);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (parsingLogs.size()>0){
|
|
|
|
+ parsingLogService.saveBatch(parsingLogs);
|
|
|
|
+ }
|
|
|
|
+ if (abnormalAlarms.size()>0){
|
|
|
|
+ abnormalAlarmService.saveBatch(abnormalAlarms);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ log.info("-----------------执行预测文件解析任务完成----------------------");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * NWP解析
|
|
|
|
+ *
|
|
|
|
+ * @param file 文件路径
|
|
|
|
+ * @return 样例集合
|
|
|
|
+ */
|
|
|
|
+ private List<NwpCloud> fileAnalysisNwp(File file, Date currentDate) {
|
|
|
|
+ List<NwpCloud> listNwp = new ArrayList<>();
|
|
|
|
+ if (file.renameTo(file)) {
|
|
|
|
+ InputStreamReader readNwp = null;
|
|
|
|
+ BufferedReader bufferedReaderNwp = null;
|
|
|
|
+ try {
|
|
|
|
+ readNwp = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);//考虑到编码格式
|
|
|
|
+ bufferedReaderNwp = new BufferedReader(readNwp);
|
|
|
|
+ String lineTxt;
|
|
|
|
+ NwpCloud nwpData;
|
|
|
|
+ BigDecimal nwpDirectRadiation = new BigDecimal("0.7"); //直接辐射
|
|
|
|
+ BigDecimal nwpDiffuseRadiation = new BigDecimal("0.3"); //散接辐射
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ String stationCode = "";
|
|
|
|
+ String forecastModel = "";
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ while ((lineTxt = bufferedReaderNwp.readLine()) != null) {
|
|
|
|
+ //NWP文件按照Tab方式截取
|
|
|
|
+ String[] datas = lineTxt.split("\t");
|
|
|
|
+
|
|
|
|
+ if (datas.length == 4 && datas[0].startsWith("<集中")) {
|
|
|
|
+ // 使用单引号分割字符串
|
|
|
|
+ stationCode = datas[1].split("'")[1];
|
|
|
|
+ forecastModel = datas[2].split("'")[1];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (!stationCode.equals("")&&!forecastModel.equals("")&&datas.length >= 35 && datas[0].startsWith("#")) {
|
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
|
+ //过滤当天的数据
|
|
|
|
+ //if (sdf.parse(datas[5]).getTime() >= TimeUtils.getMillisecondsSubDay() + 24 * 60 * 60 *
|
|
|
|
+ // 1000) {
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ Date time = sdf.parse(datas[5]);
|
|
|
|
+ Integer howLongAgo = calcHowLongAgo(currentDate, time);
|
|
|
|
+ if (howLongAgo > 0) {
|
|
|
|
+
|
|
|
|
+ nwpData = new NwpCloud();
|
|
|
|
+
|
|
|
|
+ //将截取的文件放入nwpData中
|
|
|
|
+ nwpData.setForecastHowLongAgo(howLongAgo);
|
|
|
|
+ nwpData.setForecastModel(forecastModel);
|
|
|
|
+ nwpData.setStationCode(stationCode);
|
|
|
|
+ nwpData.setTime(time);//采集时间 与 短期预测时间关联
|
|
|
|
+ nwpData.setT(NumberUtils.subtract(new BigDecimal(datas[6]), new BigDecimal("273.15")));//温度
|
|
|
|
+
|
|
|
|
+ nwpData.setSenf(new BigDecimal(datas[11]).setScale(2, RoundingMode.HALF_UP));//感热
|
|
|
|
+ nwpData.setSwr(new BigDecimal(datas[9]).setScale(2, RoundingMode.HALF_UP));//短波辐射(相当于总辐射)
|
|
|
|
+ nwpData.setLwr(new BigDecimal(datas[10]).setScale(2, RoundingMode.HALF_UP));//短波辐射(相当于总辐射)
|
|
|
|
+ nwpData.setPressure(new BigDecimal(datas[8]).setScale(2, RoundingMode.HALF_UP));//地表气压
|
|
|
|
+ nwpData.setRh(new BigDecimal(datas[7]).setScale(2, RoundingMode.HALF_UP));//2m相对湿度
|
|
|
|
+ nwpData.setDiffuseRadiation(new BigDecimal(datas[9]).multiply(nwpDiffuseRadiation).setScale(2, RoundingMode.HALF_UP));//散接辐射
|
|
|
|
+ nwpData.setDirectRadiation(new BigDecimal(datas[9]).multiply(nwpDirectRadiation).setScale(2, RoundingMode.HALF_UP));//直接辐射
|
|
|
|
+
|
|
|
|
+ nwpData.setWs10(new BigDecimal(datas[19]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs30(new BigDecimal(datas[20]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs50(new BigDecimal(datas[21]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs70(new BigDecimal(datas[22]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs80(new BigDecimal(datas[23]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs90(new BigDecimal(datas[24]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs100(new BigDecimal(datas[25]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs170(new BigDecimal(datas[26]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd10(new BigDecimal(datas[27]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd30(new BigDecimal(datas[28]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd50(new BigDecimal(datas[29]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd70(new BigDecimal(datas[30]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd80(new BigDecimal(datas[31]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd90(new BigDecimal(datas[32]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd100(new BigDecimal(datas[33]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd170(new BigDecimal(datas[34]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ if (datas.length > 35) {
|
|
|
|
+ //nwp 新增解析内容
|
|
|
|
+ nwpData.setWs20(new BigDecimal(datas[35]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs40(new BigDecimal(datas[36]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs60(new BigDecimal(datas[37]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs110(new BigDecimal(datas[38]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs120(new BigDecimal(datas[39]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs130(new BigDecimal(datas[40]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs140(new BigDecimal(datas[41]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs150(new BigDecimal(datas[42]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs160(new BigDecimal(datas[43]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs180(new BigDecimal(datas[44]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs190(new BigDecimal(datas[45]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWs200(new BigDecimal(datas[46]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd20(new BigDecimal(datas[47]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd40(new BigDecimal(datas[48]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd60(new BigDecimal(datas[49]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd110(new BigDecimal(datas[50]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd120(new BigDecimal(datas[51]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd130(new BigDecimal(datas[52]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd140(new BigDecimal(datas[53]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd150(new BigDecimal(datas[54]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd160(new BigDecimal(datas[55]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd180(new BigDecimal(datas[56]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd190(new BigDecimal(datas[57]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setWd200(new BigDecimal(datas[58]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ //下面的感觉用不上,先注释
|
|
|
|
+// nwpData.setT10(new BigDecimal(datas[59]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT20(new BigDecimal(datas[60]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT30(new BigDecimal(datas[61]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT40(new BigDecimal(datas[62]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT50(new BigDecimal(datas[63]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT60(new BigDecimal(datas[64]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT70(new BigDecimal(datas[65]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT80(new BigDecimal(datas[66]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT90(new BigDecimal(datas[67]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT100(new BigDecimal(datas[68]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT110(new BigDecimal(datas[69]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT120(new BigDecimal(datas[70]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT130(new BigDecimal(datas[71]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT140(new BigDecimal(datas[72]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT150(new BigDecimal(datas[73]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT160(new BigDecimal(datas[74]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT170(new BigDecimal(datas[75]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT180(new BigDecimal(datas[76]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT190(new BigDecimal(datas[77]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setT200(new BigDecimal(datas[78]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setDniCalcd(new BigDecimal(datas[79]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setSolarZenith(new BigDecimal(datas[80]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setClearskyGhi(new BigDecimal(datas[81]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setLcc(new BigDecimal(datas[82]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setMcc(new BigDecimal(datas[83]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setHcc(new BigDecimal(datas[84]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+// nwpData.setTcc(new BigDecimal(datas[85]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+ nwpData.setTpr(new BigDecimal(datas[86]).setScale(2, RoundingMode.HALF_UP));
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ listNwp.add(nwpData);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (IOException | ParseException | RuntimeException e) {
|
|
|
|
+ log.error("系统错误:", e);
|
|
|
|
+ File destFile = new File(file.getPath().replaceFirst("new", "error"));
|
|
|
|
+ if (destFile.exists()) {
|
|
|
|
+ destFile.delete();
|
|
|
|
+ }
|
|
|
|
+ try {
|
|
|
|
+ FileUtils.moveFile(file, destFile);
|
|
|
|
+ } catch (IOException e1) {
|
|
|
|
+ log.error(file.getName() + "文件解析失败", e);
|
|
|
|
+ }
|
|
|
|
+ } finally {
|
|
|
|
+ close(bufferedReaderNwp, readNwp);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return listNwp;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 短期解析
|
|
|
|
+ *
|
|
|
|
+ * @param file 文件路径
|
|
|
|
+ * @param currentDate 当前时间
|
|
|
|
+ * @return 样例集合
|
|
|
|
+ */
|
|
|
|
+ private List<ForecastPowerShortTermCloud> fileAnalysisShortTerm(File file, Date currentDate) {
|
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
|
+ List<ForecastPowerShortTermCloud> forecastPowerShortTerm = new ArrayList<>();
|
|
|
|
+ // 当文件未被使用时,进行解析上报
|
|
|
|
+ if (file.renameTo(file)) {
|
|
|
|
+ InputStreamReader read = null;
|
|
|
|
+ BufferedReader bufferedReader = null;
|
|
|
|
+ String stringLine;
|
|
|
|
+ ForecastPowerShortTermCloud stf;
|
|
|
|
+ try {
|
|
|
|
+ read = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);
|
|
|
|
+ bufferedReader = new BufferedReader(read);
|
|
|
|
+
|
|
|
|
+ String stationCode = "";
|
|
|
|
+ String forecastModel = "";
|
|
|
|
+
|
|
|
|
+ // 循环解析文件
|
|
|
|
+ while ((stringLine = bufferedReader.readLine()) != null) {
|
|
|
|
+
|
|
|
|
+ String[] string_arr = stringLine.split("\t");
|
|
|
|
+
|
|
|
|
+ if (string_arr.length == 4) {
|
|
|
|
+
|
|
|
|
+ if (string_arr[0].startsWith("<集中")) {
|
|
|
|
+ // 使用单引号分割字符串
|
|
|
|
+ stationCode = string_arr[1].split("'")[1];
|
|
|
|
+ forecastModel = string_arr[2].split("'")[1];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!stationCode.equals("") && !forecastModel.equals("") && string_arr[0].startsWith("#")) {
|
|
|
|
+ if (StringUtils.isNotEmpty(string_arr[2])) {
|
|
|
|
+ Date time = sdf.parse(string_arr[2]);
|
|
|
|
+ Integer howLongAgo = calcHowLongAgo(currentDate, time);
|
|
|
|
+ if (howLongAgo > 0) {
|
|
|
|
+ stf = new ForecastPowerShortTermCloud();
|
|
|
|
+ stf.setFpValue(new BigDecimal(string_arr[3]));
|
|
|
|
+ stf.setTime(time);
|
|
|
|
+ stf.setForecastHowLongAgo(howLongAgo);
|
|
|
|
+ stf.setStationCode(stationCode);
|
|
|
|
+ stf.setForecastModel(forecastModel);
|
|
|
|
+ forecastPowerShortTerm.add(stf);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ } catch (IOException | ParseException | RuntimeException e) {
|
|
|
|
+ log.error("系统错误:", e);
|
|
|
|
+ File destFile = new File(file.getPath().replaceFirst("new", "error"));
|
|
|
|
+ if (destFile.exists()) {
|
|
|
|
+ destFile.delete();
|
|
|
|
+ }
|
|
|
|
+ try {
|
|
|
|
+ FileUtils.moveFile(file, destFile);
|
|
|
|
+ } catch (IOException e1) {
|
|
|
|
+ log.error(file.getName() + "文件解析失败", e);
|
|
|
|
+ }
|
|
|
|
+ } finally {
|
|
|
|
+ close(bufferedReader, read);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return forecastPowerShortTerm;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 关闭文件流
|
|
|
|
+ *
|
|
|
|
+ * @param bufferedReader 字符数据
|
|
|
|
+ * @param read 字节流
|
|
|
|
+ */
|
|
|
|
+ private void close(BufferedReader bufferedReader, InputStreamReader read) {
|
|
|
|
+ try {
|
|
|
|
+ if (bufferedReader != null) {
|
|
|
|
+ bufferedReader.close();
|
|
|
|
+ }
|
|
|
|
+ if (read != null) {
|
|
|
|
+ read.close();
|
|
|
|
+ }
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ log.error("关闭文件流失败:", e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 计算D+x中的x
|
|
|
|
+ *
|
|
|
|
+ * @param baseTime
|
|
|
|
+ * @param time
|
|
|
|
+ */
|
|
|
|
+ public Integer calcHowLongAgo(Date baseTime, Date time) {
|
|
|
|
+ return ((int) (time.getTime() - baseTime.getTime() % 86400000L)) + 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 移动文件到临时目录下
|
|
|
|
+ *
|
|
|
|
+ * @param file 文件
|
|
|
|
+ */
|
|
|
|
+ private void moveFile(File file) {
|
|
|
|
+ // 移动文件到处理目录
|
|
|
|
+ File destFile = new File(file.getPath().replaceFirst("new", "backupsTemp"));
|
|
|
|
+ log.info("move file :{}, dest file:{}", file, destFile);
|
|
|
|
+ if (destFile.exists()) {
|
|
|
|
+ destFile.delete();
|
|
|
|
+ }
|
|
|
|
+ try {
|
|
|
|
+ FileUtils.moveFile(file, destFile);
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ log.error("系统移除文件错误:", e);
|
|
|
|
+ }
|
|
|
|
+ moveFileBackups(destFile.getParent());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 移动文件到处理目录
|
|
|
|
+ *
|
|
|
|
+ * @param filePath 文件路径
|
|
|
|
+ */
|
|
|
|
+ private void moveFileBackups(String filePath) {
|
|
|
|
+ String targetRoot = filePath.replaceFirst("backupsTemp", "backups");
|
|
|
|
+ String path = mkDirForTime(targetRoot, null);
|
|
|
|
+ path = mkDirForTime(path, "yyyy");
|
|
|
|
+ path = mkDirForTime(path, "MM");
|
|
|
|
+ path = mkDirForTime(path, "yyyyMMdd");
|
|
|
|
+ path = mkDirForTime(path, "HHmm");
|
|
|
|
+ // 移动文件夹内容
|
|
|
|
+ File sourceFile = new File(filePath);
|
|
|
|
+ if (sourceFile.exists()) {
|
|
|
|
+ try {
|
|
|
|
+ File[] files = sourceFile.listFiles();
|
|
|
|
+ if (files != null) {
|
|
|
|
+ for (File f : files) {
|
|
|
|
+ if (f.renameTo(new File(path + f.getName()))) {
|
|
|
|
+ log.info("move file :{}, dest file:{}", path, f.getName());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("文件移动失败" + e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 创建备份文件夹
|
|
|
|
+ */
|
|
|
|
+ public static String mkDirForTime(String targetRoot, String format) {
|
|
|
|
+ String path;
|
|
|
|
+ File file;
|
|
|
|
+ if (StringUtils.isNotEmpty(format)) {
|
|
|
|
+ long current = System.currentTimeMillis();
|
|
|
|
+ path = DateFormatUtils.format(current, format);
|
|
|
|
+ file = new File(targetRoot + File.separator + path + File.separator);
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ file = new File(targetRoot + File.separator);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!file.exists() && !file.isFile()) {
|
|
|
|
+
|
|
|
|
+ if (file.mkdir()) {
|
|
|
|
+ log.info("已创建文件夹");
|
|
|
|
+ } else {
|
|
|
|
+ log.info("创建文件夹失败,路径:" + file.getPath());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return file.getPath() + File.separator;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 移动文件到处理错误目录下
|
|
|
|
+ *
|
|
|
|
+ * @param file 文件
|
|
|
|
+ */
|
|
|
|
+ private void moveFileError(File file) {
|
|
|
|
+ File destFile = new File(file.getPath().replaceFirst("new", "error"));
|
|
|
|
+ if (destFile.exists()) {
|
|
|
|
+ destFile.delete();
|
|
|
|
+ }
|
|
|
|
+ try {
|
|
|
|
+ FileUtils.moveFile(file, destFile);
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ log.error(file.getName() + "文件解析失败", e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|