我正在c#.net Windows窗体应用程序中解析CSV文件,将每一行带入我创建的类中,但是我只需要访问某些列,并且接收的文件没有标准化。也就是说,存在的字段数可以不同,并且列可以出现在任何列中。
CSV示例1:
Position, LOCATION, TAG, NAME, STANDARD, EFFICIENCY, IN USE,,
1, AFT-D3, P-D3101A, EQUIPMENT 1, A, 3, TRUE
2, AFT-D3, P-D3103A, EQUIPMENT 2, B, 3, FALSE
3, AFT-D3, P-D2301A, EQUIPMENT 3, A, 3, TRUE
...
CSV示例2:
Position, TAG, STANDARD, NAME, EFFICIENCY, LOCATION, BACKUP, TESTED,,
1, P-D3101A, A, EQUIPMENT 1, 3, AFT-D3, FALSE, TRUE
2, P-D3103A, A, EQUIPMENT 2, 3, AFT-D3, TRUE, FALSE
3, P-D2301A, A, EQUIPMENT 3, 3, AFT-D3, FALSE, TRUE
...
如您所见,我永远不会知道我必须分析的文件格式,我唯一可以确定的就是它将始终包含我需要的几列。
我对此的解决方案是要求用户输入所需的列并设置为字符串,使用他们的输入将其转换为相应的整数,然后我可以将该整数用作位置。
string standardInpt = "";
string nameInpt = "";
string efficiencyInpt = "";
然后,用户输入一个从A到ZZ的值。
int standardLocation = 0;
int nameLocation = 0;
int efficiencyLocation = 0;
提交表单时。整数通过运行if else ...语句来获得最终值:
if(standard == "A")
{
standardLocation = 0;
}
else if(standard == "B")
{
standardLocation = 1;
}
...
等一直运行到VAR1 == ZZ,然后重复代码VAR2和VAR3等。
我的课程的部分内容如下:
class Equipment
{
public string Standard { get; set;}
public string Name { get; set; }
public int Efficiency { get; set; }
static Equipment FromLine(string line)
{
var data = line.split(',');
return new Equipment()
{
Standard = data[standardLocation],
Name = [nameLocation],
Efficiency = int.Parse(data[efficiencyLocation]),
};
}
}
我那里有更多代码,但是我认为这突出了我将在哪里使用变量设置索引。
我对此很陌生,我希望必须有一种更好的方法来实现这一目标,而不必编写太多可能过多,重复的If Else逻辑。我正在考虑某种查找表,但我无法弄清楚如何实现此功能,是否有关于我可以查找的指针?
答案 0 :(得分:1)
您可以通过在标题中查找列的索引来使其自动,然后使用它们从其余各行的正确位置读取值:
class EquipmentParser {
public IList<Equipment> Parse(string[] input) {
var result = new List<Equipment>();
var header = input[0].Split(',').Select(t => t.Trim().ToLower()).ToList();
var standardPosition = GetIndexOf(header, "std", "standard", "st");
var namePosition = GetIndexOf(header, "name", "nm");
var efficiencyPosition = GetIndexOf(header, "efficiency", "eff");
foreach (var s in input.Skip(1)) {
var line = s.Split(',');
result.Add(new Equipment {
Standard = line[standardPosition].Trim(),
Name = line[namePosition].Trim(),
Efficiency = int.Parse(line[efficiencyPosition])
});
}
return result;
}
private int GetIndexOf(IList<string> input, params string[] needles) {
return Array.FindIndex(input.ToArray(), needles.Contains);
}
}
答案 1 :(得分:1)
您可以使用反射和属性。
将,
中的示例写入DisplayName
属性中。
首先使用csv标头字符串作为参数调用GetIndexes
,以获取类属性和csv字段的映射字典。
然后用您刚得到的每一行和映射字典调用FromLine
。
class Equipment
{
[DisplayName("STND, STANDARD, ST")]
public string Standard { get; set; }
[DisplayName("NAME")]
public string Name { get; set; }
[DisplayName("EFFICIENCY, EFFI")]
public int Efficiency { get; set; }
// You can add any other property
public static Equipment FromLine(string line, Dictionary<PropertyInfo, int> map)
{
var data = line.Split(',').Select(t => t.Trim()).ToArray();
var ret = new Equipment();
Type type = typeof(Equipment);
foreach (PropertyInfo property in type.GetProperties())
{
int index = map[property];
property.SetValue(ret, Convert.ChangeType(data[index],
property.PropertyType));
}
return ret;
}
public static Dictionary<PropertyInfo, int> GetIndexes(string headers)
{
var headerArray = headers.Split(',').Select(t => t.Trim()).ToArray();
Type type = typeof(Equipment);
var ret = new Dictionary<PropertyInfo, int>();
foreach (PropertyInfo property in type.GetProperties())
{
var fieldNames = property.GetCustomAttribute<DisplayNameAttribute>()
.DisplayName.Split(',').Select(t => t.Trim()).ToArray();
for (int i = 0; i < headerArray.Length; ++i)
{
if (!fieldNames.Contains(headerArray[i])) continue;
ret[property] = i;
break;
}
}
return ret;
}
}
答案 2 :(得分:0)
如果有帮助,请尝试以下方法:
public int GetIndex(string input)
{
input = input.ToUpper();
char low = input[input.Length - 1];
char? high = input.Length == 2 ? input[0] : (char?)null;
int indexLow = low - 'A';
int? indexHigh = high.HasValue ? high.Value - 'A' : (int?)null;
return (indexHigh.HasValue ? (indexHigh.Value + 1) * 26 : 0) + indexLow;
}
答案 3 :(得分:-1)
您可以为此使用ASCII代码,因此无需每次添加 例如。
byte[] ASCIIValues = Encoding.ASCII.GetBytes(standard);
standardLocation = ASCIIValues[0]-65;