我收到一个必须解析的制表符分隔的文本文件。解析后,必须将这些部分分配给特定的列。
以下是我用来执行此操作的代码示例:
string path = "C:\\Users\\Robert\\Desktop\\Test.txt";
FileInfo fileInfo = new FileInfo(path);
using (StreamReader streamReader = fileInfo.OpenText())
{
string line = "";
while ((line = streamReader.ReadLine()) != null)
{
string[] columns = line.Split('\t');
Output0Buffer.AddRow();
Output0Buffer.Column0 = columns[0];
Output0Buffer.Column1 = columns[1];
Output0Buffer.Column2 = columns[2];
Output0Buffer.Column3 = columns[3];
Output0Buffer.Column4 = columns[4];
}
}
这个问题是文本文件中的某些行没有5列,当它尝试为Column4分配列的值[4]时,此代码失败(实际上,我的真实文件有21个零件,所以这更容易失败)。
如果有实际数据,如何重写这个值只能为Column4(5,6 - 21)赋值?此外,是否可以将其写入for或foreach循环以使其更整洁,因此我不必为所有21列添加一行?
非常感谢任何帮助!
答案 0 :(得分:3)
最简单的方法是将一个Columns集合添加到输出缓冲区类型,然后在for循环中设置值,例如
for(int i = 0; i < columns.Length; i++)
{
Output0Buffer.Columns[i] = columns[i];
}
如果你不能改变那种类型并且属性命名约定是一致的(即column1,2,3 ... n)那么你可以通过反射设置每个属性:
Type buffType = Output0Buffer.GetType();
for(int i = 0; i < columns.Length; i++)
{
string propertyName = String.Format("Column{0}", i);
PropertyInfo pi = buffType.GetProperty(propertyName);
pi.SetValue(buffer, columns[i], null);
}
答案 1 :(得分:1)
您没有告诉我们Output0Buffer
的定义,但最明显的解决方案是更改其定义以允许这样的索引:
int maxCol = Math.Min(columns.Length,Output0Buffer.Columns.Count);
for(int colIDx=0;colIdx<maxCol;++colIdx)
Output0Buffer.Columns[colIdx]=columns[colIdx];
(小心,那是“航空代码”。)
答案 2 :(得分:0)
您可以使用FileHelpers library。
答案 3 :(得分:0)
您可以执行类似
的操作Output0Buffer.AddRow()
for (ix = 0; ix < column.Length; ix++)
{
switch(ix)
{ case 0:
Output0Buffer.Column0 = columns[ix];
break;
case 1:
...
}
}
OutputBuffer中的列是否命名为Column0,Column1等?有什么理由说他们不能成为一个阵列吗?如果他们可以,那么你可以替换
Output0Buffer.Columns[ix] = columns[ix];
上面的整个switch语句。如果它们必须单独命名,那么我认为你必须使用反射来获得对应于列[ix]的每一列的实例成员。
我不确定,但AutoMapper可能会处理类似的事情。你可以调查一下。
答案 4 :(得分:0)
您可以尝试使用.Split(...)
上的重载。
string[] columns = (line + "\t\t\t\t").Split(new [] {'\t'}, 5);
Output0Buffer.AddRow();
Output0Buffer.Column0 = columns[0];
Output0Buffer.Column1 = columns[1];
Output0Buffer.Column2 = columns[2];
Output0Buffer.Column3 = columns[3];
// The trim is needed on this line because the split method
// will stop processing after it has hit the number of elements
// listed in the count value
Output0Buffer.Column4 = columns[4].TrimEnd('\t');
......另一种选择就是这样......
var parts = line.Split('\t');
var columns = new string[5];
if (parts.Length > columns.Length)
throw new InvalidOperationException();
Array.Copy(parts, columns, parts.Length);
// the rest of your code goes here