Mar*_*rkJ 74
Microsoft的TextFieldParser稳定,并遵循RFC 4180的CSV文件.不要被Microsoft.VisualBasic名称空间拖延; 它是.NET Framework中的标准组件,只需添加对全局Microsoft.VisualBasic程序集的引用即可.
如果您正在为Windows编译(而不是Mono)并且不期望必须解析"破坏"(不符合RFC的)CSV文件,那么这将是明显的选择,因为它是免费的,不受限制的,稳定的,并积极支持,其中大部分都不能用于FileHelpers.
另请参阅:如何:在Visual Basic中读取逗号分隔的文本文件以获取VB代码示例.
Not*_*elf 51
Kev*_*vin 21
使用OleDB连接.
String sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\InputDirectory\\;Extended Properties='text;HDR=Yes;FMT=Delimited'";
OleDbConnection objConn = new OleDbConnection(sConnectionString);
objConn.Open();
DataTable dt = new DataTable();
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM file.csv", objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
objAdapter1.Fill(dt);
objConn.Close();
Run Code Online (Sandbox Code Playgroud)
Jon*_*jap 12
如果您期望CSV解析的相当复杂的场景,甚至不要想到滚动我们自己的解析器.有很多优秀的工具,比如FileHelpers,甚至是CodeProject的工具.
关键是这是一个相当普遍的问题,你可以打赌许多软件开发人员已经考虑并解决了这个问题.
Brian为将其转换为强类型集合提供了一个很好的解决方案.
给出的大多数CSV解析方法都没有考虑转义字段或CSV文件的其他一些细微之处(如修剪字段).这是我个人使用的代码.它的边缘有点粗糙,并且几乎没有错误报告.
public static IList<IList<string>> Parse(string content)
{
IList<IList<string>> records = new List<IList<string>>();
StringReader stringReader = new StringReader(content);
bool inQoutedString = false;
IList<string> record = new List<string>();
StringBuilder fieldBuilder = new StringBuilder();
while (stringReader.Peek() != -1)
{
char readChar = (char)stringReader.Read();
if (readChar == '\n' || (readChar == '\r' && stringReader.Peek() == '\n'))
{
// If it's a \r\n combo consume the \n part and throw it away.
if (readChar == '\r')
{
stringReader.Read();
}
if (inQoutedString)
{
if (readChar == '\r')
{
fieldBuilder.Append('\r');
}
fieldBuilder.Append('\n');
}
else
{
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder = new StringBuilder();
records.Add(record);
record = new List<string>();
inQoutedString = false;
}
}
else if (fieldBuilder.Length == 0 && !inQoutedString)
{
if (char.IsWhiteSpace(readChar))
{
// Ignore leading whitespace
}
else if (readChar == '"')
{
inQoutedString = true;
}
else if (readChar == ',')
{
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder = new StringBuilder();
}
else
{
fieldBuilder.Append(readChar);
}
}
else if (readChar == ',')
{
if (inQoutedString)
{
fieldBuilder.Append(',');
}
else
{
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder = new StringBuilder();
}
}
else if (readChar == '"')
{
if (inQoutedString)
{
if (stringReader.Peek() == '"')
{
stringReader.Read();
fieldBuilder.Append('"');
}
else
{
inQoutedString = false;
}
}
else
{
fieldBuilder.Append(readChar);
}
}
else
{
fieldBuilder.Append(readChar);
}
}
record.Add(fieldBuilder.ToString().TrimEnd());
records.Add(record);
return records;
}
Run Code Online (Sandbox Code Playgroud)
请注意,这不处理字段的边缘情况,这些字段没有被双引号括起来,但是meerley在其中有一个带引号的字符串.请参阅此文章以获得更好的扩展以及一些适当库的链接.
我同意@ NotMyself.FileHelpers经过了充分的测试,可以处理各种边缘情况,如果您自己动手,最终必须处理这些边缘情况.看看FileHelpers做了什么,只有你绝对确定(1)你永远不需要处理FileHelpers所做的边缘情况,或者(2)你喜欢写这种东西并打算当你必须解析这样的东西时,我会高兴极了:
1,"比尔","史密斯","主管","没有评论"
2,'德雷克',''奥马利',"看门人,
哎呀,我没有引用,我正在换新线!
我很无聊所以我修改了一些我写的东西.它尝试以OO方式封装解析,减少通过文件的迭代量,它只在顶层foreach迭代一次.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// usage:
// note this wont run as getting streams is not Implemented
// but will get you started
CSVFileParser fileParser = new CSVFileParser();
// TO Do: configure fileparser
PersonParser personParser = new PersonParser(fileParser);
List<Person> persons = new List<Person>();
// if the file is large and there is a good way to limit
// without having to reparse the whole file you can use a
// linq query if you desire
foreach (Person person in personParser.GetPersons())
{
persons.Add(person);
}
// now we have a list of Person objects
}
}
public abstract class CSVParser
{
protected String[] deliniators = { "," };
protected internal IEnumerable<String[]> GetRecords()
{
Stream stream = GetStream();
StreamReader reader = new StreamReader(stream);
String[] aRecord;
while (!reader.EndOfStream)
{
aRecord = reader.ReadLine().Split(deliniators,
StringSplitOptions.None);
yield return aRecord;
}
}
protected abstract Stream GetStream();
}
public class CSVFileParser : CSVParser
{
// to do: add logic to get a stream from a file
protected override Stream GetStream()
{
throw new NotImplementedException();
}
}
public class CSVWebParser : CSVParser
{
// to do: add logic to get a stream from a web request
protected override Stream GetStream()
{
throw new NotImplementedException();
}
}
public class Person
{
public String Name { get; set; }
public String Address { get; set; }
public DateTime DOB { get; set; }
}
public class PersonParser
{
public PersonParser(CSVParser parser)
{
this.Parser = parser;
}
public CSVParser Parser { get; set; }
public IEnumerable<Person> GetPersons()
{
foreach (String[] record in this.Parser.GetRecords())
{
yield return new Person()
{
Name = record[0],
Address = record[1],
DOB = DateTime.Parse(record[2]),
};
}
}
}
}
Run Code Online (Sandbox Code Playgroud)