我正在使用Filehelper 3.1.5来解析CSV文件,但我的问题是CSV文件应该支持许多可选列,而我还没有找到为此任务配置FileHelper。
以下是一个例子:
[DelimitedRecord(";")]
[IgnoreEmptyLines]
public class TestRecord
{
//Mandatory
[FieldNotEmpty]
public string A;
[FieldOptional]
public string B;
[FieldOptional]
public string C;
}
我希望能够处理这样的数据:
A;C
TestA1;TestC1
TestA2;TestC1
但是当我解析它时,我会得到“TestC1”作为记录的结果[1] .B
var engine = new FileHelperEngine<TestRecord>();
var records = engine.ReadFile("TestAC.csv");
string column = records[1].C;
Assert.IsTrue(column.Equals("TestC1")); //Fails, returns ""
column = records[1].B;
Assert.IsTrue(column.Equals("TestC1")); //True, but that was not what I wanted
感谢任何建议!
答案 0 :(得分:0)
我认为你应该用标题装饰你的专栏,例如:
[DelimitedRecord(";")]
[IgnoreEmptyLines]
public class TestRecord
{
//Mandatory
[FieldNotEmpty, FieldOrder(0), FieldTitle("A")]
public string A;
[FieldOptional, FieldOrder(1), FieldTitle("B")]
public string B;
[FieldOptional, FieldOrder(2), FieldTitle("C")]
public string C;
}
这样,运行时知道列名是什么,并相应地解析它们。否则,它只知道你在文件中有两列,并期望额外的分号。因此,以下内容适用于您的原始设置:
A;;C
TestA1;;TestC1
TestA2;;TestC1
这仅适用于FileHelpers v2,因为v3不再具有FieldTitle
答案 1 :(得分:0)
针对文件助手版本3.2.5进行测试
为了使FileHelper.Engine正确识别您的列,您必须动态删除不再使用的字段。以下是基于您的代码和一些添加的位并从控制台程序运行:
string tempFile = System.IO.Path.GetTempFileName();
System.IO.File.WriteAllText(tempFile, @"A;C\r\n\TestA1;TestC1\r\nTestA2;TestC1");
var engine = new FileHelperEngine<TestRecord>();
var records = engine.ReadFile(tempFile, 1);
// Get the header text from the file
var headerFile = engine.HeaderText.Replace("\r", "").Replace("\n", "");
// Get the header from the engine record layout
var headerFields = engine.GetFileHeader();
// Test fixed string against column as column could be null and Debug.Assert can't use .Equals on a null object!
string column = records[0].C;
Debug.Assert("TestC1".Equals(column), "Test 1 - Column C does not equal 'TestC1'"); //Fails, returns ""
// Test fixed string against column as column could be null and Debug.Assert can't use .Equals on a null object!
column = records[0].B;
Debug.Assert(!"TestC1".Equals(column), "Test 1 - Column B does equal 'TestC1'"); //True, but that was not what I wanted
// Create a new engine otherwise we get some random error from Dynamic.Assign once we start removing fields
// which is presumably because we have called ReadFile() before hand.
engine = new FileHelperEngine<TestRecord>();
if (headerFile != headerFields)
{
var fieldHeaders = engine.Options.FieldsNames;
var fileHeaders = headerFile.Split(';').ToList();
// Loop through all the record layout fields and remove those not found in the file header
for (int index = fieldHeaders.Length - 1; index >= 0; index--)
if (!fileHeaders.Contains(fieldHeaders[index]))
engine.Options.RemoveField(fieldHeaders[index]);
}
headerFields = engine.GetFileHeader();
Debug.Assert(headerFile == headerFields);
var records2 = engine.ReadFile(tempFile);
// Test fixed string against column as column could be null and Debug.Assert can't use .Equals on a null object!
column = records2[0].C;
Debug.Assert("TestC1".Equals(column), "Test 2 - Column C does not equal 'TestC1'"); //Fails, returns ""
// Test fixed string against column as column could be null and Debug.Assert can't use .Equals on a null object!
column = records2[0].B;
Debug.Assert(!"TestC1".Equals(column), "Test 2 - Column B does equal 'TestC1'"); //True, but that was not what I wanted
Console.WriteLine("Seems to be OK now!");
Console.ReadLine();
注意:我发现一个重要的事情是,在当前版本3.2.5中,在读取文件的第一行后删除一个字段会导致引擎烧断!
我还在您的类中添加了一个IgnoreFirst()属性,以便它跳过标题行并将忽略的文本设置为engine.HeaderText
。这导致以下类:
[DelimitedRecord(";")]
[IgnoreEmptyLines]
[IgnoreFirst()]
public class TestRecord
{
//Mandatory
[FieldNotEmpty]
public string A;
[FieldOptional]
public string B;
[FieldOptional]
public string C;
}