CSVファイルの内容を読み込んでデータセットを作成したいと考えています。私はこのようにしようとしています:
var lines = File.ReadAllLines("test.csv").Select(a => a.Split(';'));
DataSet ds = new DataSet();
ds.load(lines);
しかし、明らかにこれは正しくありません。
SELECT
データセットを埋めるために、CSV ファイルに対してステートメントを実行する必要があります。
編集: http://carllbrown.blogspot.co.uk/2007/09/populate-dataset-from-csv-delimited_18.htmlのサンプル コードを次に示します。
string FileName = ...
OleDbConnection conn = new OleDbConnection
("Provider=Microsoft.Jet.OleDb.4.0; Data Source = " +
Path.GetDirectoryName(FileName) +
"; Extended Properties = \"Text;HDR=YES;FMT=Delimited\"");
conn.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter
("SELECT * FROM " + Path.GetFileName(FileName), conn);
DataSet ds = new DataSet("Temp");
adapter.Fill(ds);
conn.Close();
次に、Fast CSV Readerのようなライブラリを使用できます
using System.IO;
using LumenWorks.Framework.IO.Csv;
void ReadCsv()
{
// open the file "data.csv" which is a CSV file with headers
using (CsvReader csv = new CsvReader(
new StreamReader("data.csv"), true))
{
myDataRepeater.DataSource = csv;
myDataRepeater.DataBind();
}
}
コンマ (,) このコードで解決される問題
セルの間にコンマ(,)を追加しても機能します
CSV ファイルの読み取りコード:
public MainWindow()
{
InitializeComponent();
DataTable dtDataSource = new DataTable();
string[] fileContent = File.ReadAllLines(@"..\\Book1.csv");
if (fileContent.Count() > 0)
{
//Create data table columns dynamically
string[] columns = fileContent[0].Split(',');
for (int i = 0; i < columns.Count(); i++)
{
dtDataSource.Columns.Add(columns[i]);
}
//Add row data dynamically
for (int i = 1; i < fileContent.Count(); i++)
{
string[] rowData = fileContent[i].Split(',');
string[] realRowData = new string[columns.Count()];
StringBuilder collaboration = new StringBuilder();
int v = 0;
//this region solves the problem of a cell containing ",".
#region CommaSepProblem
for (int j = 0, K = 0; j < rowData.Count(); j++, K++)
{
if ((rowData[j].Count(x => x == '"') % 2 == 0))//checks if the string contains even number of DoubleQuotes
{
realRowData[K] = quotesLogic((rowData[j]));
}
else if ((rowData[j].Count(x => x == '"') % 2 != 0))//If Number of DoubleQuotes are ODD
{
int c = rowData[j].Count(x => x == '"');
v = j;
while (c % 2 != 0)//Go through all the next array cell till it makes EVEN Number of DoubleQuotes.
{
collaboration.Append(rowData[j] + ",");
j++;
c += rowData[j].Count(x => x == '"');
}
collaboration.Append(rowData[j]);
realRowData[K] = quotesLogic(collaboration.ToString());
}
else { continue; }
}
#endregion
dtDataSource.Rows.Add(realRowData);
}
if (dtDataSource != null)
{
//dataGridView1 = new DataGridView();
dataGrid1.ItemsSource = dtDataSource.DefaultView;
}
}
}
メソッドを追加する必要があります:
string quotesLogic(string collaboration)
{
StringBuilder after = new StringBuilder(collaboration);
if (after.ToString().StartsWith("\"") && after.ToString().EndsWith("\""))//removes 1st and last quotes as those are system generated
{
after.Remove(0, 1);
after.Remove(after.Length - 1, 1);
int count = after.Length - 1;
//FACT: if you try to add DoubleQuote in a cell in excel. It'll save that quote as 2 times DoubleQuote(Like "") which means first DoubleQuote is to give instruction to CPU that the next DoubleQuote is not system generated.
while (count > 0)//This loop find twice insertion of 2 DoubleQuotes and neutralise them to One DoubleQuote.
{
if (after[count] == '"' && after[count - 1] == '"')
{
after.Remove(count, 1);
}
count--;
}
}
return after.ToString();
}
CSV ファイル (または Excel から直接貼り付けたもの) のサンプル データで満たされた DataTable をすばやく作成して、試したりプロトタイプを作成したりしたい場合は、Shan Carter の Mr. Data Converter のフォークを使用できます。最近、機能を追加しました。コンマおよびタブ区切りのデータを C# DataTable に出力します。
以下に、Csv ファイルを DataTable に変換する 5 つのメソッドを記述しました。
オプションの引用符 (" 記号など) を考慮し、他のライブラリを使用せずに可能な限り多用途になるように設計されています。
public static DataTable GetDataTabletFromCSVFile(string filePath, bool isHeadings)
{
DataTable MethodResult = null;
try
{
using (TextFieldParser TextFieldParser = new TextFieldParser(filePath))
{
if (isHeadings)
{
MethodResult = GetDataTableFromTextFieldParser(TextFieldParser);
}
else
{
MethodResult = GetDataTableFromTextFieldParserNoHeadings(TextFieldParser);
}
}
}
catch (Exception ex)
{
ex.HandleException();
}
return MethodResult;
}
public static DataTable GetDataTableFromCsvString(string csvBody, bool isHeadings)
{
DataTable MethodResult = null;
try
{
MemoryStream MemoryStream = new MemoryStream();
StreamWriter StreamWriter = new StreamWriter(MemoryStream);
StreamWriter.Write(csvBody);
StreamWriter.Flush();
MemoryStream.Position = 0;
using (TextFieldParser TextFieldParser = new TextFieldParser(MemoryStream))
{
if (isHeadings)
{
MethodResult = GetDataTableFromTextFieldParser(TextFieldParser);
}
else
{
MethodResult = GetDataTableFromTextFieldParserNoHeadings(TextFieldParser);
}
}
}
catch (Exception ex)
{
ex.HandleException();
}
return MethodResult;
}
public static DataTable GetDataTableFromRemoteCsv(string url, bool isHeadings)
{
DataTable MethodResult = null;
try
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
StreamReader StreamReader = new StreamReader(httpWebResponse.GetResponseStream());
using (TextFieldParser TextFieldParser = new TextFieldParser(StreamReader))
{
if (isHeadings)
{
MethodResult = GetDataTableFromTextFieldParser(TextFieldParser);
}
else
{
MethodResult = GetDataTableFromTextFieldParserNoHeadings(TextFieldParser);
}
}
}
catch (Exception ex)
{
ex.HandleException();
}
return MethodResult;
}
private static DataTable GetDataTableFromTextFieldParser(TextFieldParser textFieldParser)
{
DataTable MethodResult = null;
try
{
textFieldParser.SetDelimiters(new string[] { "," });
textFieldParser.HasFieldsEnclosedInQuotes = true;
string[] ColumnFields = textFieldParser.ReadFields();
DataTable dt = new DataTable();
foreach (string ColumnField in ColumnFields)
{
DataColumn DataColumn = new DataColumn(ColumnField);
DataColumn.AllowDBNull = true;
dt.Columns.Add(DataColumn);
}
while (!textFieldParser.EndOfData)
{
string[] Fields = textFieldParser.ReadFields();
for (int i = 0; i < Fields.Length; i++)
{
if (Fields[i] == "")
{
Fields[i] = null;
}
}
dt.Rows.Add(Fields);
}
MethodResult = dt;
}
catch (Exception ex)
{
ex.HandleException();
}
return MethodResult;
}
private static DataTable GetDataTableFromTextFieldParserNoHeadings(TextFieldParser textFieldParser)
{
DataTable MethodResult = null;
try
{
textFieldParser.SetDelimiters(new string[] { "," });
textFieldParser.HasFieldsEnclosedInQuotes = true;
bool FirstPass = true;
DataTable dt = new DataTable();
while (!textFieldParser.EndOfData)
{
string[] Fields = textFieldParser.ReadFields();
if(FirstPass)
{
for (int i = 0; i < Fields.Length; i++)
{
DataColumn DataColumn = new DataColumn("Column " + i);
DataColumn.AllowDBNull = true;
dt.Columns.Add(DataColumn);
}
FirstPass = false;
}
for (int i = 0; i < Fields.Length; i++)
{
if (Fields[i] == "")
{
Fields[i] = null;
}
}
dt.Rows.Add(Fields);
}
MethodResult = dt;
}
catch (Exception ex)
{
ex.HandleException();
}
return MethodResult;
}
私のように、レポート サービスから節約している場合は、次のように使用する必要があります。
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string filenameExtension;
byte[] bytes = rvMain.ServerReport.Render("csv", null, out mimeType, out encoding, out filenameExtension, out streamids, out warnings);
string CsvBody = System.Text.Encoding.UTF8.GetString(bytes);
DataTable dt = GetDataTableFromCsvString(CsvBody,true);
それ以外の場合は、次のことだけを行う必要があります。
bool IsHeadings = true; //Does the data include a heading row?
DataTable dt = GetDataTableFromCsvString(CsvBody, IsHeadings);
またはcsvファイルから直接使用する
bool IsHeadings = true; //Does the data include a heading row?
DataTable dt = GetDataTabletFromCsvFile(FilePath, IsHeadings)
または、リモートに保存されている csv ファイルを使用するには
bool IsHeadings = true; //Does the data include a heading row?
DataTable dt = GetDataTabletFromRemoteCsv(Url, IsHeadings)
Dataset は DataTables のコレクションなので、次のように作成します。
DataSet ds = new DataSet();
ds.Tables.Add(dt);