如何在 FileHelpers 中使用动态 CSV 分隔符?
问题: 我需要读取 CSV 文件。 我使用 FileHelpers 库来实现此目的。
问题是我需要一个动态分隔符(用户定义),这意味着任何东西都可以作为分隔符(逗号、分号、制表符、换行符,还有其他任何东西)。
问题是,FileHelpers 在属性中定义了分隔符,这意味着在编译时。这使得动态地完成它变得不可能。
我能做的就是声明一个新类,它继承自一个基类,并在这个新类上设置分隔符。
[FileHelpers.DelimitedRecord(",")]
public class CommaCustomer : BaseCustomer
{
}
这样我只需为每个新的分隔符在基类中进行更改。 问题是,我不能(也不想)为每个可能的分隔符创建一个子类。
这是我到目前为止的代码:
using System;
using System.Data;
using System.IO;
//using FileHelpers;
//using FileHelpers.RunTime;
namespace Examples
{
class MainClass
{
[STAThread]
static void Main()
{
FileHelpers.FileHelperEngine engine = new FileHelpers.FileHelperEngine(typeof(SemicolonCustomer));
// To read use:
string str = @"D:\Username\Desktop\FileHelpers_Examples_CSharp_VbNet\Data\SemicolonCustomers.txt";
//str = @"D:\Username\Desktop\FileHelpers_Examples_CSharp_VbNet\Data\CustomersDelimited.txt";
SemicolonCustomer[] custs = (SemicolonCustomer[])engine.ReadFile(str);
//Customer[] custs = (Customer[]) engine.ReadFile("yourfile.txt");
foreach (SemicolonCustomer cli in custs)
{
Console.WriteLine();
Console.WriteLine("Customer: " + cli.CustId.ToString() + " - " + cli.Name);
Console.WriteLine("Added Date: " + cli.AddedDate.ToString("d-M-yyyy"));
Console.WriteLine("Balance: " + cli.Balance.ToString());
Console.WriteLine();
Console.WriteLine("-----------------------------");
} // Next cli
Console.ReadKey();
Console.WriteLine("Writing data to a delimited file...");
Console.WriteLine();
// To write use:
//engine.WriteFile("myyourfile.txt", custs);
//If you are using .NET 2.0 or greater is
//better if you use the Generics version:
// FileHelperEngine engine = new FileHelperEngine<Customer>();
// To read use (no casts =)
// Customer[] custs = engine.ReadFile("yourfile.txt");
// To write use:
// engine.WriteFile("yourfile.txt", custs);
} // End Sub Main
} // End Class MainClass
//------------------------
// RECORD CLASS (Example, change at your will)
// TIP: Remember to use the wizard to generate this class
public class BaseCustomer
{
public int CustId;
public string Name;
public decimal Balance;
[FileHelpers.FieldConverter(FileHelpers.ConverterKind.Date, "ddMMyyyy")]
public DateTime AddedDate;
}
[FileHelpers.DelimitedRecord(";")]
public class SemicolonCustomer : BaseCustomer
{
}
[FileHelpers.DelimitedRecord(",")]
public class CommaCustomer : BaseCustomer
{
}
}
是否可以在运行时编译子类
[FileHelpers.DelimitedRecord(\"" + delimiter + "\")]
public class AnyDelimiterCustomer : BaseCustomer
{
}
然后在代码中引用此运行时编译的类?
Question:
I need to read a CSV file.
I use the FileHelpers library to achieve this.
The problem is I need a dynamic delimiter (user defined), meaning anything can be delimiter (Comma, semicolon, tab, newline, but also anything else).
The problem is, FileHelpers defines the delimiter in an attribute, which means at compile-time. This makes it impossible to do it dynamically.
What I can do is declare a new class, which inherits from one base class, and set the delimiter on this new class.
[FileHelpers.DelimitedRecord(",")]
public class CommaCustomer : BaseCustomer
{
}
That way I only have to make changes in the base class for every new delimiter.
The problem is, this is I can't (and don't want to) create a child class for every possible delimiter.
This is the code I have so far:
using System;
using System.Data;
using System.IO;
//using FileHelpers;
//using FileHelpers.RunTime;
namespace Examples
{
class MainClass
{
[STAThread]
static void Main()
{
FileHelpers.FileHelperEngine engine = new FileHelpers.FileHelperEngine(typeof(SemicolonCustomer));
// To read use:
string str = @"D:\Username\Desktop\FileHelpers_Examples_CSharp_VbNet\Data\SemicolonCustomers.txt";
//str = @"D:\Username\Desktop\FileHelpers_Examples_CSharp_VbNet\Data\CustomersDelimited.txt";
SemicolonCustomer[] custs = (SemicolonCustomer[])engine.ReadFile(str);
//Customer[] custs = (Customer[]) engine.ReadFile("yourfile.txt");
foreach (SemicolonCustomer cli in custs)
{
Console.WriteLine();
Console.WriteLine("Customer: " + cli.CustId.ToString() + " - " + cli.Name);
Console.WriteLine("Added Date: " + cli.AddedDate.ToString("d-M-yyyy"));
Console.WriteLine("Balance: " + cli.Balance.ToString());
Console.WriteLine();
Console.WriteLine("-----------------------------");
} // Next cli
Console.ReadKey();
Console.WriteLine("Writing data to a delimited file...");
Console.WriteLine();
// To write use:
//engine.WriteFile("myyourfile.txt", custs);
//If you are using .NET 2.0 or greater is
//better if you use the Generics version:
// FileHelperEngine engine = new FileHelperEngine<Customer>();
// To read use (no casts =)
// Customer[] custs = engine.ReadFile("yourfile.txt");
// To write use:
// engine.WriteFile("yourfile.txt", custs);
} // End Sub Main
} // End Class MainClass
//------------------------
// RECORD CLASS (Example, change at your will)
// TIP: Remember to use the wizard to generate this class
public class BaseCustomer
{
public int CustId;
public string Name;
public decimal Balance;
[FileHelpers.FieldConverter(FileHelpers.ConverterKind.Date, "ddMMyyyy")]
public DateTime AddedDate;
}
[FileHelpers.DelimitedRecord(";")]
public class SemicolonCustomer : BaseCustomer
{
}
[FileHelpers.DelimitedRecord(",")]
public class CommaCustomer : BaseCustomer
{
}
}
Is it somehow possible at runtime to compile a child class
[FileHelpers.DelimitedRecord(\"" + delimiter + "\")]
public class AnyDelimiterCustomer : BaseCustomer
{
}
And then reference this runtime compiled class in code ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我刚刚意识到有一个
DelimitedFileEngine
可以用另一种方式解决您的问题。您可以直接去
似乎
BaseCustomer
需要用[DelimitedRecord]
属性进行装饰,否则会引发异常,但分隔符会被提供给的任何内容覆盖>engine.Options.Delimiter
。以下示例使用标记为条分隔符的格式导入逗号分隔记录。
I just realized there is a
DelimitedFileEngine
which solves your problem another way.You can just go
It seems that
BaseCustomer
needs to be decorated with a[DelimitedRecord]
attribute, otherwise an exception is raised but the delimiter is overridden by whatever is supplied toengine.Options.Delimiter
.The following example imports a comma delimited record using a format which is marked as bar delimited.
不,那不可能。
但是您可以使用 FileHelper
DelimitedClassBuilder
构建动态文件解析器,您可以在运行时设置分隔符:No thats not possible.
But you can use the FileHelper
DelimitedClassBuilder
to build a dynamic file parser where you can set the delimiter at runtime:您可以使用运行时类。你有两个选择。 从字符串编译你的类
例如
或者,你可以使用DelimitedClassBuilder 类。
You can use runtime classes. You have two choices. Either compile your class from a string
For instance
Or alternatively, you can use the DelimitedClassBuilder class.
这是可能的。
但只能通过将序列化类型移动到单独的程序集中。
像这样:
SerializationTypes Assembly:
It is possible.
But only by moving the serialization type into a separate assembly.
Like this:
SerializationTypes Assembly:
也许您想使用 Microsoft 的 TextFieldParser .VisualBasic.FileIO 命名空间:
Maybe you want to use the TextFieldParser from Microsoft.VisualBasic.FileIO Namespace:
添加强制转换为我解决了问题 (FileHelpers V3.5.1)
var engine = new DelimitedFileEngine(typeof(BaseCustomer));
((FileHelpers.Options.DelimitedRecordOptions)engine.Options).Delimiter=",";
adding a cast solves the problem for me (FileHelpers V3.5.1)
var engine = new DelimitedFileEngine(typeof(BaseCustomer));
((FileHelpers.Options.DelimitedRecordOptions)engine.Options).Delimiter=",";