回答
不幸的是,這是LGPL,這是不理想的企業環境... – 2009-05-14 01:44:07
@John,你爲什麼這麼說?LGPL不要求您發佈任何代碼,除非您修改庫本身。 (在這種情況下,無論如何提交補丁都是有意義的。) – 2009-08-24 06:19:43
+1剛纔實現了這個...真棒 – 2010-02-03 20:30:00
一個很好的簡單方法是打開文件,並將每行讀入數組,鏈表,數據結構選擇。但要小心處理第一行。
這可能會在你的頭上,但似乎有一種直接的方式來訪問它們以及使用connection string。
爲什麼不嘗試使用Python而不是C#或VB?它有一個很好的CSV模塊導入,爲你做所有繁重的工作。
如果您可以保證數據中沒有逗號,那麼最簡單的方法可能是使用String.split。
例如:
String[] values = myString.Split(',');
myObject.StringField = values[0];
myObject.IntField = Int32.Parse(values[1]);
有可能是你可以用它來幫助圖書館,但是這可能是因爲你可以得到簡單。只要確保數據中不能有逗號,否則您需要更好地解析它。
CodeProject上有兩篇文章提供解決方案的代碼,其中一篇使用StreamReader,另一篇使用Microsoft Text Driver使用imports CSV data。
我很無聊,所以我修改了一些我寫的東西。它嘗試以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]),
};
}
}
}
}
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;
}
注意這不會處理不被雙引號deliminated領域的邊緣情況,但有它內部的引用字符串meerley。請參閱this post以獲得更好的擴展,以及一些鏈接到某些正確的庫。
我必須在.NET中使用.NET的CSV解析器來處理今年夏天的項目,並在Microsoft Jet文本驅動程序中解決。使用連接字符串指定文件夾,然後使用SQL Select語句查詢文件。您可以使用schema.ini文件指定強類型。起初我沒有這樣做,但後來我的數據類型不是很明顯,例如IP號碼或像「XYQ 3.9 SP1」這樣的條目,結果很糟糕。
我碰到的一個限制是它無法處理64個字符以上的列名;它截斷。這不應該是一個問題,除非我正在處理設計非常糟糕的輸入數據。它返回一個ADO.NET數據集。
這是我找到的最佳解決方案。我會警惕地推出我自己的CSV解析器,因爲我可能會錯過一些最終案例,並且我沒有發現任何其他免費的CSV解析包。
編輯:另外,每個目錄只能有一個schema.ini文件,所以我動態地附加到它以強烈鍵入所需的列。它只會強制鍵入指定的列,並推斷任何未指定的字段。我非常欣賞這一點,因爲我正在處理導入流體70+列CSV的問題,並且不想指定每一列,而僅僅是那些行爲不當的列。
如果您預計複雜的CSV解析方案,甚至不會想到自己翻譯我們自己的解析器。那裏有很多優秀的工具,如FileHelpers,甚至是CodeProject。
關鍵是這是一個相當普遍的問題,你可以打賭很多軟件開發人員已經考慮和解決了這個問題。
我同意@NotMyself。 FileHelpers已經過很好的測試,可以處理各種邊緣情況,如果你自己動手處理,你最終必須處理這些情況。看一看FileHelpers的功能,只有在你確信(1)你永遠不需要處理FileHelpers所做的邊緣案例時,或者(2)你喜歡寫這種東西,並且將要喜出望外,當你要解析這樣的東西:
1, 「條例」, 「史密斯」, 「監督員」,
2, '德雷克', '奧馬利' 「無可奉告」, 「看門人,
哎呀,我沒有報價,我在一個新行!
使用的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();
微軟的TextFieldParser是穩定的,並且CSV文件的RFC 4180如下。不要被Microsoft.VisualBasic
命名空間推遲;它是.NET Framework中的標準組件,只需添加對全局組件的引用即可。
如果您正在編譯Windows(而不是Mono),並且預計不需要解析「損壞」(不符合RFC的)CSV文件,那麼這將是明顯的選擇,因爲它是免費的,無限制,穩定和積極支持,其中大部分不能用於FileHelpers。
另請參閱:How to: Read From Comma-Delimited Text Files in Visual Basic瞭解VB代碼示例。
我輸入了一些代碼。 datagridviewer中的結果看起來不錯。它將一行文本解析爲一個對象的數組列表。
enum quotestatus
{
none,
firstquote,
secondquote
}
public static System.Collections.ArrayList Parse(string line,string delimiter)
{
System.Collections.ArrayList ar = new System.Collections.ArrayList();
StringBuilder field = new StringBuilder();
quotestatus status = quotestatus.none;
foreach (char ch in line.ToCharArray())
{
string chOmsch = "char";
if (ch == Convert.ToChar(delimiter))
{
if (status== quotestatus.firstquote)
{
chOmsch = "char";
}
else
{
chOmsch = "delimiter";
}
}
if (ch == Convert.ToChar(34))
{
chOmsch = "quotes";
if (status == quotestatus.firstquote)
{
status = quotestatus.secondquote;
}
if (status == quotestatus.none)
{
status = quotestatus.firstquote;
}
}
switch (chOmsch)
{
case "char":
field.Append(ch);
break;
case "delimiter":
ar.Add(field.ToString());
field.Clear();
break;
case "quotes":
if (status==quotestatus.firstquote)
{
field.Clear();
}
if (status== quotestatus.secondquote)
{
status =quotestatus.none;
}
break;
}
}
if (field.Length != 0)
{
ar.Add(field.ToString());
}
return ar;
}
- 1. .NET中的CSV文件導入
- 2. 導入CSV文件
- 3. 導入CSV文件
- 4. 導入CSV文件導入Hadoop的
- 5. 導入CSV文件導入的pgsql
- 6. 導入CSV文件導入使用C#
- 7. 導入CSV文件導入使用python
- 8. 導入CSV文件導入PSQL分貝
- 9. 導入大型CSV文件導入Gephi
- 10. 導入CSV文件中的Neo4j
- 11. 將.CSV文件導入SQLite
- 12. CSV文件導入SkFlow
- 13. VBA:導入CSV文件
- 14. 導入CSV文件到MySQL
- 15. 如何導入csv文件
- 16. 導入許多csv文件
- 17. PHP導入CSV文件
- 18. 導入CSV文件OLEDB C#
- 19. 從CSV文件導入PHP
- 20. 導入CSV文件較大
- 21. 將CSV文件導入JTable
- 22. symfony文件導入(csv)
- 23. CSV文件導入到Python
- 24. 從MSSQL導入MySql CSV CSV文件
- 25. SQL使用.Net導出爲CSV文件
- 26. 在Netsuite中自動導入CSV文件?
- 27. 在MySQL中導入CSV文件RDBMS
- 28. 在R中導入CSV文件
- 29. 將CSV文件導入到Java中
- 30. 如何導入CSV文件MongoDB中
這是http://stackoverflow.com/questions/1103495/is-there-a-proper-way-to-read-csv-files – 2011-02-18 16:46:53
的副本考慮這是不是1103495創建上年同期,我認爲這個問題是這個問題的重複。 – MattH 2011-05-26 05:16:23
謝謝,馬特。我只是試圖將它們連接在一起,而不是指明哪一個先出現。你會看到我在這個問題上有完全相同的問題。是否有更好的方法將兩個問題聯繫在一起? – 2011-05-27 13:48:28