/// <summary> /// 讀取 nc 檔存入 OcmData 物件 /// </summary> /// <param name="ncFilePath"></param> /// <returns></returns> public OcmData GetOcmNetCdfData(string ncFilePath) { OcmData _ocm_data = new OcmData(); OcmHeader _ocmHeader = new OcmHeader(); List <object> _data = new List <object>(); NcFile ncFile = new NcFile(ncFilePath); //OCM 的 nc 檔 if (ncFile.DimensionCount == 4) { float min_Intensity = 0; float max_Intensity = 0; foreach (NcVar curVar in ncFile.Variables) { // 取得 header 屬性 switch (curVar.ComponentName) { case "time": _ocmHeader.refTime = (string)this.GetNcAttValueByVariables(curVar, "units"); break; case "lat": _ocmHeader.la1 = (int)(((double[])GetNcAttValueByVariables(curVar, "maximum"))[0]); _ocmHeader.la2 = (int)(((double[])GetNcAttValueByVariables(curVar, "minimum"))[0]); _ocmHeader.dy = ((double[])GetNcAttValueByVariables(curVar, "resolution"))[0]; _ocmHeader.ny = (int)curVar.ElementCount; break; case "lon": _ocmHeader.lo1 = (int)(((double[])GetNcAttValueByVariables(curVar, "minimum"))[0]); _ocmHeader.lo2 = (int)(((double[])GetNcAttValueByVariables(curVar, "maximum"))[0]); _ocmHeader.dx = ((double[])GetNcAttValueByVariables(curVar, "resolution"))[0]; _ocmHeader.nx = (int)curVar.ElementCount; break; case "UCURR": case "VCURR": _ocmHeader.parameterCategory = 2; break; case "SALT": case "SST": case "WL": _ocmHeader.parameterCategory = 0; break; } switch (curVar.ComponentName) { case "UCURR": _ocmHeader.parameterNumber = 2; break; case "VCURR": _ocmHeader.parameterNumber = 3; break; case "SALT": case "SST": case "WL": _ocmHeader.parameterNumber = 0; break; } // 填入 data curVar.ReadData(); switch (curVar.ComponentName) { case "UCURR": case "VCURR": case "SALT": case "SST": case "WL": float[] _datafloat = ((NcVarTyped <float>)curVar).Data; for (int i = 0; i < _datafloat.Length; i++) { if (_datafloat[i].Equals(-999)) { _data.Add(""); } else { float _df = float.Parse(_datafloat[i].ToString("f5")); _data.Add(_df); min_Intensity = (_df < min_Intensity) ? _df : min_Intensity; max_Intensity = (_df > max_Intensity) ? _df : max_Intensity; } } //curVar.Attributes.AsQueryable().Where(o => o.ComponentName.Equals(""){ obj}) break; } } _ocm_data.minimum = min_Intensity; _ocm_data.maximum = max_Intensity; _ocm_data.average = (min_Intensity + max_Intensity) / 2; _ocm_data.header = _ocmHeader; _ocm_data.data = _data; } return(_ocm_data); }
static void Main(string[] args) { var param = ParseString(Environment.CommandLine); if (param.Count == 0) { Console.WriteLine("================================"); Console.WriteLine("請搭配輸入指令使用本程式"); Console.WriteLine("--------------------------------"); Console.WriteLine("指令說明: \n"); Console.WriteLine("--------------------------------"); Console.WriteLine(" -callEvent (必填)處理資料集代碼 \n"); Console.WriteLine("--------------------------------"); Console.WriteLine(" Ex. -callEvent = isoheXMLtoJson \n"); Console.WriteLine(" isoheXMLtoJson : 運研所海氣象資料下載轉檔 - 商港觀測資料 "); Console.WriteLine(" ocmUVncToJson : OPeNDAP OCM 資料下載轉檔 - 海流 UV "); Console.WriteLine(" ocmSALTncToJson : OPeNDAP OCM 資料下載轉檔 - SALT 海表鹽度 "); Console.WriteLine(" ocmSSTncToJson : OPeNDAP OCM 資料下載轉檔 - SST 海表溫度 "); Console.WriteLine(" ocmWLncToJson : OPeNDAP OCM 資料下載轉檔 - WL 海面高 "); Console.WriteLine(" delFolder : 刪除資料夾 (提供刪除下載資料原始檔存放的資料夾)"); Console.WriteLine(" "); Console.WriteLine("--------------------------------"); Console.WriteLine(" -targetPath (必填)資料輸出存放資料夾路徑 \n"); Console.WriteLine("--------------------------------"); Console.WriteLine(" Ex. -targetPath = \"C:\\OpenDataTrans\\isoheStation\" \n"); Console.WriteLine(" "); Console.WriteLine("--------------------------------"); Console.WriteLine(" -dataTime (選填)指定要下載的 OPeNDAP OCM 資料集時間(不指定時會自動判斷是抓今日或昨日有資料的源) \n"); Console.WriteLine("--------------------------------"); Console.WriteLine($" Ex. -dataTime = {DateTime.Now.ToString("yyyyMMdd")} (指定抓 OPeNDAP 上 YYYYMMDD 的資料源) \n"); Console.WriteLine($" Ex. -dataTime = onlyNow (只會抓取當小時最新的 1 筆資料) "); Console.WriteLine(" "); Console.WriteLine("================================"); //不關閉視窗讓使用者看說明 Console.ReadKey(); } else { Console.WriteLine("================================"); Console.WriteLine("您目前輸入的參數"); Console.WriteLine("--------------------------------"); foreach (KeyValuePair<string, string> kv in param) { Console.WriteLine("Key={0} Value={1}",kv.Key, kv.Value); } Console.WriteLine("--------------------------------"); // 必填參數 if (param.ContainsKey("callEvent") && param.ContainsKey("targetPath")) { Console.WriteLine("程式執行開始"); //自訂處理工具 RWLib_NetCDF rwLibNetcdf = new RWLib_NetCDF(); RWLib_Date rwLibDate = new RWLib_Date(); RWLib_Net rwLibNet = new RWLib_Net(); RWLib_FileIO rwLibFio = new RWLib_FileIO(); // 指令 - 作業種類代碼 string callEvent = param["callEvent"]; // 指令 - 作業目錄位置 string argFileOrOutFolderPath = param["targetPath"]; Console.WriteLine(callEvent); Console.WriteLine(argFileOrOutFolderPath); #region 運研所海氣象資料下載轉檔 - 商港觀測資料 if (callEvent.Equals("isoheXMLtoJson")) { RWLib_Log rwLibisoheLog = new RWLib_Log(@$"{argFileOrOutFolderPath}\log\", "isoheStations"); //https://isohe.ihmt.gov.tw/ rwLibisoheLog.log("運研所海氣象資料轉檔 --- Begin"); // XML 下載存放路徑 string isoheXMLsavePath = @$"{argFileOrOutFolderPath}\xml\"; rwLibFio.DelAndCreateFolder(isoheXMLsavePath); // 產出 JSON 檔案路徑 string outJsonFolderPath = @$"{argFileOrOutFolderPath}\json\"; string outJsonFilePath = @$"{outJsonFolderPath}isoheStations.json"; // 商港觀測站 OpenData (裡面有很多觀測站沒有 OpenData 所以自己建要爬的資料集) // https://isohe.ihmt.gov.tw/station/OpenData/XML/GetSAstationXML.aspx // 有 OpenData 的資料集 (代碼,港名,opendata資料集編號) string isoheStations = "KL,基隆港,127851|SA,蘇澳港,127855|HL,花蓮港,127852|TC,臺中港,127831|KH,高雄港,127853|TP,臺北港,127836|BD,布袋港,127840|AP,安平港,127846|NG,馬祖南竿,127847"; //isoheStations = "KL,基隆港,127851"; // 測試只單抓一個商港 // 準備下載資訊的資料集 List<isoheStation> isoheStationList = new List<isoheStation>(); foreach (string sta in isoheStations.Split("|")) { isoheStation staObj = new isoheStation(); staObj.Code = sta.Split(",")[0]; staObj.Name = sta.Split(",")[1]; staObj.XmlSourceUrl = $"https://isohe.ihmt.gov.tw/station/OpenData/XML/Get{sta.Split(",")[0]}stationXML.aspx"; staObj.OpendataLinkUrl = $"https://data.gov.tw/dataset/{sta.Split(",")[2]}"; isoheStationList.Add(staObj); } List<Station> _stationList = new List<Station>(); foreach (isoheStation sta in isoheStationList) { rwLibisoheLog.log($">>>> " + sta.XmlSourceUrl); string xmlFilePath = $"{isoheXMLsavePath}{sta.Code}_Station.xml"; //下載資料 var success = rwLibNet.DownloadFile(sta.XmlSourceUrl, xmlFilePath); rwLibisoheLog.log($"{sta.Code}_Station 下載狀態 " + success); if (success) { //讀取 XML XmlDocument doc = new XmlDocument(); doc.Load(xmlFilePath); List<HistoryDataItem> hisDataList = new List<HistoryDataItem>(); List<TideDataItem> tideDataList = new List<TideDataItem>(); List<WindDataItem> windDataList = new List<WindDataItem>(); StationLocation hisStLoc = new StationLocation(); StationLocation tideStLoc = new StationLocation(); StationLocation windStLoc = new StationLocation(); // 塞入資料到物件 foreach (XmlNode xn in doc.ChildNodes.Item(1).ChildNodes) { switch (xn.Name) { case "History": HistoryDataItem _hisItem = new HistoryDataItem(); double _hisLat = xn.SelectSingleNode("Latitude") == null ? 0.0 : double.Parse(xn.SelectSingleNode("Latitude").InnerText); double _hisLng = xn.SelectSingleNode("Longitude") == null ? 0.0 : double.Parse(xn.SelectSingleNode("Longitude").InnerText); hisStLoc.Latitude = (hisStLoc.Latitude == 0.0) ? _hisLat : ((_hisLat + hisStLoc.Latitude) / 2); hisStLoc.Longitude = (hisStLoc.Longitude == 0.0) ? _hisLng : ((_hisLng + hisStLoc.Longitude) / 2); //這邊的節點項目有可能會不存在!! 線上資料集沒說明值的內容若是 -999.99 是什麼意思 _hisItem.Date_Time = xn.SelectSingleNode("Date_Time") == null ? "" : xn.SelectSingleNode("Date_Time").InnerText; _hisItem.HS = xn.SelectSingleNode("HS") == null ? 0.0 : double.Parse(xn.SelectSingleNode("HS").InnerText); _hisItem.TP = xn.SelectSingleNode("TP") == null ? 0.0 : double.Parse(xn.SelectSingleNode("TP").InnerText); _hisItem.MDIR = xn.SelectSingleNode("MDIR") == null ? 0.0 : double.Parse(xn.SelectSingleNode("MDIR").InnerText); _hisItem.Tmean = xn.SelectSingleNode("Tmean") == null ? 0.0 : double.Parse(xn.SelectSingleNode("Tmean").InnerText); _hisItem.Velocity = xn.SelectSingleNode("Velocity") == null ? 0.0 : double.Parse(xn.SelectSingleNode("Velocity").InnerText); _hisItem.Vmdir = xn.SelectSingleNode("Vmdir") == null ? 0.0 : double.Parse(xn.SelectSingleNode("Vmdir").InnerText); hisDataList.Add(_hisItem); break; case "WindData": WindDataItem _windItem = new WindDataItem(); double _windLat = xn.SelectSingleNode("Latitude") == null ? 0.0 : double.Parse(xn.SelectSingleNode("Latitude").InnerText); double _windLng = xn.SelectSingleNode("Longitude") == null ? 0.0 : double.Parse(xn.SelectSingleNode("Longitude").InnerText); windStLoc.Latitude = (windStLoc.Latitude == 0.0) ? _windLat : ((_windLat + windStLoc.Latitude) / 2); windStLoc.Longitude = (windStLoc.Longitude == 0.0) ? _windLng : ((_windLng + windStLoc.Longitude) / 2); _windItem.Date_Time = xn.SelectSingleNode("Date_Time") == null ? "" : xn.SelectSingleNode("Date_Time").InnerText; _windItem.WD_AVG = xn.SelectSingleNode("WD_AVG") == null ? 0.0 : double.Parse(xn.SelectSingleNode("WD_AVG").InnerText); _windItem.WS_AVG = xn.SelectSingleNode("WS_AVG") == null ? 0.0 : double.Parse(xn.SelectSingleNode("WS_AVG").InnerText); windDataList.Add(_windItem); break; case "TideData": TideDataItem _tideItem = new TideDataItem(); double _tideLat = xn.SelectSingleNode("Latitude") == null ? 0.0 : double.Parse(xn.SelectSingleNode("Latitude").InnerText); double _tideLng = xn.SelectSingleNode("Longitude") == null ? 0.0 : double.Parse(xn.SelectSingleNode("Longitude").InnerText); tideStLoc.Latitude = (tideStLoc.Latitude == 0.0) ? _tideLat : ((_tideLat + tideStLoc.Latitude) / 2); tideStLoc.Longitude = (tideStLoc.Longitude == 0.0) ? _tideLng : ((_tideLng + tideStLoc.Longitude) / 2); _tideItem.Date_Time = xn.SelectSingleNode("Date_Time") == null ? "" : xn.SelectSingleNode("Date_Time").InnerText; _tideItem.TideValue = xn.SelectSingleNode("TideValue") == null ? 0.0 : double.Parse(xn.SelectSingleNode("TideValue").InnerText); tideDataList.Add(_tideItem); break; } } Station _station = new Station() { Name = sta.Name, Code = sta.Code, OpendataLinkUrl = sta.OpendataLinkUrl, XmlSourceUrl = sta.XmlSourceUrl, DataSet = new StationDataSet() { HistoryData = new HistoryData() { location = hisStLoc, Data = hisDataList } , TideData = new TideData() { location = tideStLoc, Data = tideDataList } , WindData = new WindData() { location = windStLoc, Data = windDataList } } }; _stationList.Add(_station); } } // 組合各港觀測資料 StationList stationList = new StationList() { FieldsDesc = new FieldsDesc() { StationFieldsDesc = new StationFieldsDesc(), HistoryDataFieldsDesc = new HistoryDataFieldsDesc(), TideDataFieldsDesc = new TideDataFieldsDesc(), WindDataFieldsDesc = new WindDataFieldsDesc() } , Stations = _stationList }; // 判斷成功轉出的測試數量與組合的數量相同,則轉出 JSON 檔 if (_stationList.Count == isoheStationList.Count) { rwLibFio.DelAndCreateFolder(outJsonFolderPath); string json = JsonConvert.SerializeObject(stationList); rwLibisoheLog.log($"產出 JSON 檔 {outJsonFilePath}"); System.IO.File.WriteAllText(outJsonFilePath, json); } else { rwLibisoheLog.log($"XML 檔下載數量 [{_stationList.Count}] 不同於測站數量 [{ isoheStationList.Count}], 不進行 JSON 檔更新"); } rwLibisoheLog.log("運研所海氣象資料轉檔 --- End "); } #endregion #region OPeNDAP OCM 資料下載轉檔 - 海流 UV、海表鹽度、海表溫度、海面高 if (callEvent.Equals("ocmSALTncToJson") || callEvent.Equals("ocmSSTncToJson") || callEvent.Equals("ocmWLncToJson") || callEvent.Equals("ocmUVncToJson") || callEvent.Equals("ocmNcToJson") ) { #region 讀取參數設定 OCM 要抓取資料的自訂日期 // OPeNDAP OCM 資料來源網址 string cwbOpenDapOcmUrl = $"http://med.cwb.gov.tw/opendap/hyrax/OCM/"; // Ocm 資料是否只抓當下最新的 1 筆 bool onlyTransNowData = false; // Ocm 資料日期路徑 string argOcmDataObtainDate = DateTime.Now.ToString("yyyyMMdd"); if (!rwLibNet.ChekUrlRequestStatus($"{cwbOpenDapOcmUrl}{argOcmDataObtainDate}/")) { // 自動取得目前 OCM 的資料是今日或昨日 argOcmDataObtainDate = DateTime.Now.AddDays(-1).ToString("yyyyMMdd"); Console.WriteLine($" OPeNDAP OCM 資料最新日期為 {argOcmDataObtainDate} \n"); } // 指定下載資料的日期 if (param.ContainsKey("dataTime")) { string parm_dataTime = param["dataTime"]; parm_dataTime = parm_dataTime.Split('"')[0].Trim(); if (parm_dataTime.IndexOf("onlyNow") != -1) onlyTransNowData = true; else if(parm_dataTime.Length == 8) argOcmDataObtainDate = parm_dataTime; } #endregion string ncTypeCode = ""; switch (callEvent) { case "ocmSALTncToJson": ncTypeCode = "SALT"; break; case "ocmSSTncToJson": ncTypeCode = "SST"; break; case "ocmWLncToJson": ncTypeCode = "WL"; break; case "ocmUVncToJson"://OPeNDAP OCM 資料下載轉檔 - 海流 UV ncTypeCode = "UCURR,VCURR"; break; } RWLib_Log rwLibOcmLog = new RWLib_Log($@"{argFileOrOutFolderPath}\log\", ncTypeCode); rwLibOcmLog.log($"========================================================================="); rwLibOcmLog.log($" OPeNDAP OCM 資料下載轉檔 ---- Begin \n"); if (!ncTypeCode.Equals("")) { try { //下載時間資料集數量 (目前 OPeNDAP OCM 資料集完整時間為 120) int downloadNcTimeItemCount = 120; //下載資料 存放路徑 string progFileSaveFolderPath = $@"{argFileOrOutFolderPath}\"; string nc_FolderPath = $@"{progFileSaveFolderPath}nc\"; string json_Temp_FolderPath = $@"{progFileSaveFolderPath}jsonTemp\"; string json_FolderPath = $@"{progFileSaveFolderPath}json\"; // 下載失敗重新嘗試次數 int reTryDownloadTimes = 5; // 清空下載及暫存的資料夾 rwLibFio.DelAndCreateFolder(nc_FolderPath); rwLibFio.DelAndCreateFolder(json_Temp_FolderPath); // (1) 建立一 ocmIndexList 記錄 nc 下載成功數量 // (2) 跑各類別 ncTypeCode 的 nc 檔下載作業,將結果記錄於上述 List // (3) 檢查 List 中各類別成功下載 nc 檔的數量是否大於 0 且能被 類別 ncTypeCode 數量整除 // (4) 進行 json 轉檔 // (5) 整理 index 資料,轉出 index json 檔 string[] _ncTypeCodes = ncTypeCode.Split(","); int ncTypeCount = 0; List<OcmDataIndex> ocmIndexList = new List<OcmDataIndex>(); foreach (string _ncTypeCode in _ncTypeCodes) { rwLibOcmLog.log($"處理資料集 {_ncTypeCode} ; 整體進度 {ncTypeCount + 1}/{_ncTypeCodes.Length} \n"); string ncTimeFilePath = @$"{nc_FolderPath}{_ncTypeCode}times.nc"; //先確認設定日期的時間檔是否存在,有存在才進行檔案的下載作業 rwLibOcmLog.log($"時間集 nc 檔連線狀態檢查 \n"); string ocm_TimeNcUrl = $"{cwbOpenDapOcmUrl}{argOcmDataObtainDate}/00/9999/{_ncTypeCode}.{argOcmDataObtainDate}00.nc.nc?time[0:1:119]"; rwLibOcmLog.log($"{ocm_TimeNcUrl}\n"); if (rwLibNet.ChekUrlRequestStatus(ocm_TimeNcUrl)) { rwLibOcmLog.log($"時間集 nc 檔連線狀態檢查 OK!! \n"); rwLibOcmLog.log($"> 開始下載 {ocm_TimeNcUrl} 到 {ncTimeFilePath}"); var successTimeNc = rwLibNet.DownloadFile(ocm_TimeNcUrl, ncTimeFilePath); if (successTimeNc) { rwLibOcmLog.log($">> 時間集 nc 檔下載成功 \n"); // 解析 times 檔中的時段 NcFile ncTimeFile = new NcFile(ncTimeFilePath); ncTimeFile.Variables[0].ReadData(); int[] _times = ((NcVarTyped<int>)ncTimeFile.Variables[0]).Data; rwLibOcmLog.log($"取得時間資料集數量 [{_times.ToList().Count}]"); if (_times.ToList().Count == 120) { rwLibOcmLog.log($"時間資料集數量檢核正確,開始進行 nc 檔下載 \n"); int i = 0; int ncDataCount = 0;// nc檔下載數量 int historyDataCount = 0;//歷史資料集數量 foreach (var time in _times.ToList()) { // 建立單一時間集的 nc資料索引記錄物件檔 OcmDataIndex ocmIndex = new OcmDataIndex(); ocmIndex.Index = i; // 取得 UTC 轉換後的時間 ocmIndex.Time = time; DateUtc_08 dtUtc08 = rwLibDate.GetUtcAnd08DateTimeFromHours(time); ocmIndex.time08 = dtUtc08.time08; ocmIndex.timeUTC = dtUtc08.timeUTC; string dataDTimeHourName = dtUtc08.dt08.ToString("yyyyMMddHH"); // 只轉目前日期小時以後的預報資料 if (DateTime.Compare(dtUtc08.dt08, DateTime.Now.AddHours(-1)) > 0) { // nc 資料集下載網址 ocmIndex.ncDataUrl = $"{cwbOpenDapOcmUrl}{argOcmDataObtainDate}/00/9999/{_ncTypeCode}.{argOcmDataObtainDate}00.nc.nc?{_ncTypeCode}[{i}:1:{i}][0:1:0][0:1:1160][0:1:640]"; // nc 資料存放位址 ocmIndex.ncFilePath = $"{nc_FolderPath}{i}_{_ncTypeCode}_{dataDTimeHourName}.nc"; // json file name ocmIndex.name = $"{dataDTimeHourName}_{_ncTypeCode}.json"; // 下載 nc 檔 bool successNCdata = rwLibNet.DownloadFile(ocmIndex.ncDataUrl, ocmIndex.ncFilePath); if (successNCdata) { rwLibOcmLog.log($">> {i}_{_ncTypeCode} 資料集 nc 檔 下載成功\n"); ocmIndexList.Add(ocmIndex); ncDataCount++; } else { rwLibOcmLog.log($">> {i}_{_ncTypeCode} 資料集 nc 檔 下載失敗 !!!!!!!!!!!!!!!!!!"); // 重新下載嘗試 bool successNCdata_try = false; if (!successNCdata) { for (int j = 0; j < reTryDownloadTimes; j++) { rwLibOcmLog.log($">> {i}_{_ncTypeCode} 資料集 nc 檔 嘗試重新下載 第 {j + 1} 次"); successNCdata_try = rwLibNet.DownloadFile(ocmIndex.ncDataUrl, ocmIndex.ncFilePath); if (successNCdata_try) { rwLibOcmLog.log($">> {i}_{_ncTypeCode} 資料集 nc 檔 嘗試重新下載成功\n"); ocmIndexList.Add(ocmIndex); ncDataCount++; break; } else rwLibOcmLog.log($">> {i}_{_ncTypeCode} 資料集 nc 檔 嘗試重新下載失敗 !!!!!!!!!!!!!!!!!!\n"); } } } // 設置為 onlyNow 只抓最新 1 次的資料 if (onlyTransNowData) // 當成功抓取第 1 份資料時 if (ncDataCount == 1) { rwLibOcmLog.log($"目前設置為 onlyNow 只抓取目前時間的資料\n"); // 重設本次作業應跑過的時間集數量 downloadNcTimeItemCount = historyDataCount + 1; break; } } else { rwLibOcmLog.log($"[{i}][{time}][{dataDTimeHourName}] 資料集已為歷史資料,不進行下載\n"); historyDataCount++; } i++; if (i == downloadNcTimeItemCount) break; } rwLibOcmLog.log($" nc 檔下載數量為 [{ncDataCount}] ; 歷史 nc 檔不下載的數量為 [{historyDataCount}]\n"); } else { rwLibOcmLog.log($"取得時間資料集數量 [{_times.ToList().Count}] 不為 120,停止\n"); } } else { rwLibOcmLog.log($">> 時間集 nc 檔下載失敗"); rwLibOcmLog.log($">> {successTimeNc} {ocm_TimeNcUrl}"); rwLibOcmLog.log($">> 停止下載所有 nc 檔\n"); } } else { rwLibOcmLog.log($"{argOcmDataObtainDate} 時間集 nc 檔連線狀態檢查 失敗,不執行資料下載更新作業。\n "); } ncTypeCount++; } Console.WriteLine($"ocmIndexList.Count {ocmIndexList.Count} (有 nc 檔的 time 數量)"); if (ocmIndexList.Count > 0 && (ocmIndexList.Count % _ncTypeCodes.Length) == 0) { rwLibOcmLog.log($"開始進行 JSON 轉檔 \n"); int jsonCount = 0;//轉出的 json 檔數量 rwLibOcmLog.log($"> JSON 轉檔輸出 Temp 路徑 {json_Temp_FolderPath}"); int oneTypeNcCount = ocmIndexList.Count / _ncTypeCodes.Length;//單一類別下載的 nc 檔數量 List<OcmDataIndex> _outOcmIndexList = new List<OcmDataIndex>();//整理後輸出的 index 物件 #region 轉出 json 檔 for (int t = 0; t < oneTypeNcCount; t++) {//time List<OcmData> _ocm_datalist = new List<OcmData>(); OcmDataIndex _outOcmIndex = new OcmDataIndex(); string dataDTimeHourName = ""; for (int tc = 0; tc < _ncTypeCodes.Length; tc++) {//typecode int index = t + (tc * oneTypeNcCount); OcmDataIndex odi = ocmIndexList[index]; OcmData _od = rwLibNetcdf.GetOcmNetCdfData(odi.ncFilePath); _ocm_datalist.Add(_od); //將最大、最小值更新至 Index 中 if (_ncTypeCodes.Length == 1) { odi.max_Intensity = _od.maximum; odi.min_Intensity = _od.minimum; } _outOcmIndex = odi; dataDTimeHourName = odi.name.Split('_')[0]; } //整理要輸出的資料項目內容 var _outDataList = from _ocmdata in _ocm_datalist select new { _ocmdata.header, _ocmdata.data }; string json = JsonConvert.SerializeObject(_outDataList); string outJsonFileName = $"{dataDTimeHourName}_{string.Join("_", _ncTypeCodes)}.json"; string outJsonFilePath = $"{json_Temp_FolderPath}{outJsonFileName}"; File.WriteAllText(outJsonFilePath, json); rwLibOcmLog.log($">> 轉出 {outJsonFileName} 檔\n"); jsonCount++; // 更新 index 的 json 路徑 _outOcmIndex.name = outJsonFileName; _outOcmIndexList.Add(_outOcmIndex); } #endregion #region 整理 index 資料,轉出 index json 檔 //輸出索引檔 ocmIndexList 轉 json //篩選輸出於 json 中的屬性項目 string jsonIndex = ""; if (_ncTypeCodes.Length > 1) { jsonIndex = JsonConvert.SerializeObject(from data in _outOcmIndexList select new { data.timeUTC, data.time08, data.name }); } else { jsonIndex = JsonConvert.SerializeObject(from data in _outOcmIndexList select new { data.timeUTC, data.time08, data.name, data.min_Intensity, data.max_Intensity, }); } string outJsonIndexFilePath = $"{json_Temp_FolderPath}index.json"; rwLibOcmLog.log($"轉出 index.json 索引檔 {outJsonIndexFilePath} \n"); File.WriteAllText(outJsonIndexFilePath, jsonIndex); #endregion // 更新至正式 json 位置 if (jsonCount == _outOcmIndexList.Count) { rwLibOcmLog.log($"json 轉出數量符合 nc 檔數量 [{jsonCount}] ,進行正式資料更新替換\n"); //若正式輸出 json 目錄不存在則建立資料夾 rwLibFio.DelAndCreateFolder(json_FolderPath); //當輸出成功時,將 json 檔移到成功的目錄中替換 DirectoryInfo di = new DirectoryInfo(json_Temp_FolderPath); foreach (FileInfo jsonFI in di.GetFiles("*.json")) { string moveToPath = $"{json_FolderPath}{jsonFI.Name}"; jsonFI.MoveTo(moveToPath, true); rwLibOcmLog.log($"> 移動 {jsonFI.Name} 檔案至 {moveToPath}\n"); } } else { //若未轉出成功,則不替換正式目錄中的 json 資料 rwLibOcmLog.log($"json 轉出數量不完整 {jsonCount},停止更新替換正式資料\n"); } } } catch (Exception ex) { rwLibOcmLog.log($"try catch Exception: {ex.Message} {ex.StackTrace}\n\n"); } } else { rwLibOcmLog.log($" 無法識別的代碼 \n"); } rwLibOcmLog.log($" OPeNDAP OCM 資料下載轉檔 ---- End\n\n"); } #endregion #region 刪除資料夾 (提供刪除下載資料原始檔存放的資料夾) if (callEvent.Equals("delFolder")) { Console.WriteLine("刪除資料夾 --- Begin"); try { Console.WriteLine($"刪除資料夾 {argFileOrOutFolderPath}\n"); // 清空或刪除資料夾 if (System.IO.Directory.Exists(argFileOrOutFolderPath)) System.IO.Directory.Delete(argFileOrOutFolderPath, true); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } Console.WriteLine("刪除資料夾 End"); } #endregion Console.WriteLine("程式執行結束"); } } }