关于使用 C# 处理水位数据多种格式的统一转换
1、前言
YAC9900 水位雨量存储器有很多固件版本,SD 卡存储的数据存在多种数据格式。统一转换数据格式精简优化编程代码。
同时多种版本的文件在打开对话框进行多选文件,合并所有月份的数据,整合数据文件。
2、水位数据的多种格式
因 YAC9900 版本不同,SD卡存储数据格式有四种情况
1、日期、时间、水位(Z:)、雨量(PT:)、电压(VT:)
"2024/03/31 23:55:00 Z:28.29 PT:976.5 VT:12.91",
2、数据个数、日期、时间、水位(Z:)、雨量(PT:)、电压(VT:)
"num1120 2024/07/02 09:45:00 Z:34.94 PT:269.5 VT:14.24",
3、日期、时间、水位、雨量、电压
"2024/04/30 23:55:00 29.179 277.5 12.71",
4、每30分钟记录水位,其它无水位:
"2021/01/01 00:00:00 Z:27.37 PT:0 VT:11.31",
"2021/01/01 00:05:00 PT:0 VT:11.33",
"2021/01/01 00:10:00 PT:0 VT:11.36",
"2021/01/01 00:15:00 PT:0 VT:11.30",
"2021/01/01 00:20:00 PT:0 VT:11.31",
"2021/01/01 00:25:00 PT:0 VT:11.32",
"2021/01/01 00:30:00 Z:27.36 PT:0 VT:11.23",
从上面数据可以看出,以空格分解;
设定以第一列为日期,则后面依次是:第二列为时间,则第三列为水位,第四列为雨量,第五列为设备电压。
3、水位数据多种格式的统一转换程序展示
4、水位数据多种格式的统一转换 C# 代码
4.1、声明引用命名空间
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Globalization;
4.2、多种格式的统一转换 C# 代码
Array.Sort(FilesList);//打开对话框选择多个 SD 卡数据文件后,进行文件字符串排序
//Console.WriteLine("文件列表: " + String.Join("\r\n", x));
string FilePathName = FilesList[0];
int Pos = FilePathName.LastIndexOf(".");
List<string> WaterLevelAndRain = new List<string>();
foreach (string FileStr in FilesList)
{
using (StreamReader sr = new StreamReader(FileStr))
{
string line;
while ((line = sr.ReadLine()) != null)
{
WaterLevelAndRain.Add(line);//将多文件的所有数据添加到LIST列表
}
}
}
//Console.WriteLine("原始列表: " + String.Join("\r\n", WaterLevelAndRain));
WaterLevelAndRain.RemoveAll(str => string.IsNullOrEmpty(str));//删除LIST空值
WaterLevelAndRain = WaterLevelAndRain.Distinct().ToList();//删除LIST重复项,即删除 行数据 重复值
string[] WR = WaterLevelAndRain.ToArray();//转换为数组
WaterLevelAndRain.Clear();//清除列表,,释放内存空间
int WRL = WR.Length;
//Console.WriteLine(WR.Length);
DateTime[] DataDT = new DateTime[WRL];
Double[] WL = new double[WRL];
Double[] RL = new double[WRL];
for (int i = 0; i < WRL; i++)
{
string[] split = WR[i].Split(',', ' ', '\t');//以逗号、空格、制表符分裂
int num1 = split[0].IndexOf("num");
int num2;
if (num1 == 0)//前有num,新YAC9900前有数据个数标志 num
{
DataDT[i] = DateTime.Parse(split[1] + " " + split[2]);//整合为时间序列
num2 = split[3].IndexOf(":");//水位有前缀的按冒号分裂
if (num2 > 0)
{
int num3 = split[3].IndexOf("Z:");
if (num3 == -1)//数据无水位:
{
WL[i] = -20000;//假定为无效水位,没有正常读取传感器的水位
int index = split[3].IndexOf(':') + 1;
string R = split[3].Substring(index);
RL[i] = Convert.ToDouble(R);
}
else
{
int index = split[3].IndexOf(':') + 1;
string W = split[3].Substring(index);
index = split[4].IndexOf(':') + 1;
string R = split[4].Substring(index);
WL[i] = Convert.ToDouble(W);
RL[i] = Convert.ToDouble(R);
}
}
else
{
WL[i] = Convert.ToDouble(split[3]);
RL[i] = Convert.ToDouble(split[4]);
}
}
else if (num1 == -1)//前无num
{
int test = split[0].IndexOf('/');
if (test > 4)//旧YAC_BUG,在日期数据前出现文件名
{
split[0] = split[0].Substring(test - 4);
}
DataDT[i] = DateTime.Parse(split[0] + " " + split[1]);
num2 = split[2].IndexOf(":");
if (num2 > 0)
{
int num3 = split[2].IndexOf("Z:");
if (num3 == -1)//无水位:
{
WL[i] = -20000;//假定为无效水位
int index = split[2].IndexOf(':') + 1;
string R = split[2].Substring(index);
RL[i] = Convert.ToDouble(R);
}
else
{
int index = split[2].IndexOf(':') + 1;
string W = split[2].Substring(index);
index = split[3].IndexOf(':') + 1;
string R = split[3].Substring(index);
WL[i] = Convert.ToDouble(W);
RL[i] = Convert.ToDouble(R);
}
}
else
{
WL[i] = Convert.ToDouble(split[2]);
RL[i] = Convert.ToDouble(split[3]);
}
}
//Console.WriteLine(String.Join(",", split));
//Console.WriteLine(DataDT[i]);
//Console.WriteLine(WL[i]);
//Console.WriteLine(RL[i]);
//Console.WriteLine();
}
4.3、多种格式的统一转换 C# 代码,文件输出保存
string StartDate = DataDT[0].ToString("yyyy年MM月dd日", CultureInfo.InvariantCulture);//获取数据的开始日期
string EneDate = DataDT[WRL - 1].ToString("yyyy年MM月dd日", CultureInfo.InvariantCulture);//获取数据的结束日期
string RainFilePathName = FilePathName.Substring(0, Pos) + "-" + StartDate + "至" + EneDate + "雨量" + FilePathName.Substring(Pos);
string WaterLevelFilePathName = FilePathName.Substring(0, Pos) + "-" + StartDate + "至" + EneDate + "水位" + FilePathName.Substring(Pos);
FileStream SaveWLFS = new FileStream(WaterLevelFilePathName, FileMode.Create);
StreamWriter SWWLFS = new StreamWriter(SaveWLFS, Encoding.GetEncoding("gb2312"));
FileStream SaveRAFS = new FileStream(RainFilePathName, FileMode.Create);
StreamWriter SWRAFS = new StreamWriter(SaveRAFS, Encoding.GetEncoding("gb2312"));
for (int i = 0; i < WRL; i++)
{
string OutWL = "";
string OutRA = "";
if (i == 0 && WL[i] != -20000)
{
OutWL = DataDT[i].ToString("yyyy/MM/dd HH:mm ", CultureInfo.InvariantCulture) + ((int)(WL[i] * 100)).ToString("000000");
OutRA = DataDT[i].ToString("yyyy/MM/dd HH:mm ", CultureInfo.InvariantCulture) + RL[i].ToString("0000.0");
}
else if (WL[i] != -20000 && DataDT[i] != DataDT[i - 1])
{
OutWL = DataDT[i].ToString("yyyy/MM/dd HH:mm ", CultureInfo.InvariantCulture) + ((int)(WL[i] * 100)).ToString("000000");
OutRA = DataDT[i].ToString("yyyy/MM/dd HH:mm ", CultureInfo.InvariantCulture) + RL[i].ToString("0000.0");
}
else if (i == WRL - 1 && WL[i] == -20000)//最后一个是-20000
{
OutWL = "";
OutRA = DataDT[i].ToString("yyyy/MM/dd HH:mm ", CultureInfo.InvariantCulture) + RL[i].ToString("0000.0");
}
else if (i > 0 && WL[i] == -20000 && WL[i + 1] != -20000 && WL[i - 1] != -20000 && Math.Abs(WL[i + 1] - WL[i - 1]) <= 0.03 && DataDT[i] != DataDT[i - 1])
{
WL[i] = (WL[i + 1] + WL[i - 1]) / 2;
OutWL = DataDT[i].ToString("yyyy/MM/dd HH:mm ", CultureInfo.InvariantCulture) + ((int)(WL[i] * 100)).ToString("000000");
OutRA = DataDT[i].ToString("yyyy/MM/dd HH:mm ", CultureInfo.InvariantCulture) + RL[i].ToString("0000.0");
}
else
{
OutWL = "";
OutRA = DataDT[i].ToString("yyyy/MM/dd HH:mm ", CultureInfo.InvariantCulture) + RL[i].ToString("0000.0");
}
if (OutWL != "")
{
SWWLFS.WriteLine(OutWL);
}
SWRAFS.WriteLine(OutRA);
OutWL = "";
OutRA = "";
//Console.WriteLine(OutWL);
//Console.WriteLine();
// OutSTR = DataDT[i].ToString("yy/MM/dd hh:mm ", CultureInfo.InvariantCulture) + RL[i].ToString("0000.0");
}
SWWLFS.Flush();//关闭打开的文件,释放内存空间
SWWLFS.Close();
SWRAFS.Flush();
SWRAFS.Close();
Array.Clear(DataDT, 0, WRL);//关闭数组,释放内存空间
Array.Clear(WL, 0, WRL);
Array.Clear(RL, 0, WRL);