2 * Karinto Library Project
\r
4 * This software is distributed under a zlib-style license.
\r
5 * See license.txt for more information.
\r
10 using System.Collections.Generic;
\r
12 using System.Text.RegularExpressions;
\r
17 public class CsvReader<TDataTable> where TDataTable : DataTable, new()
\r
19 #region private fields
\r
21 private string separator;
\r
22 private Regex sepPattern;
\r
23 private TDataTable protoType;
\r
24 private DataColumnCollection cols;
\r
26 private delegate bool Parser(ref string input, out object output);
\r
27 static private Dictionary<Type, Parser> parsers;
\r
28 private Parser[] lineParser;
\r
32 #region constructors
\r
35 parsers = new Dictionary<Type, Parser>();
\r
36 parsers[typeof(Double)] = ParseDouble;
\r
42 protoType = new TDataTable();
\r
43 cols = protoType.Columns;
\r
44 lineParser = new Parser[cols.Count];
\r
45 for(int i = 0; i < cols.Count; ++i)
\r
47 Type t = cols[i].DataType;
\r
48 if (parsers[t] != null)
\r
50 lineParser[i] = parsers[t];
\r
54 lineParser[i] = ParseString;
\r
65 public string Separator
\r
74 sepPattern = new Regex(separator, RegexOptions.Compiled);
\r
80 #region public methods
\r
82 public TDataTable Read(FilePath path)
\r
84 TDataTable table = new TDataTable();
\r
87 using (FileStream fs = new FileStream(
\r
88 path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
\r
90 using (StreamReader reader = new StreamReader(fs))
\r
92 while (reader.Peek() >= 0)
\r
94 DataRow row = table.NewRow();
\r
95 string line = reader.ReadLine();
\r
99 if (table.Rows.Count < 1)
\r
101 SetHeader(table.Columns, line);
\r
105 table.Rows.Add(row);
\r
110 catch (Exception ex)
\r
117 public TDataTable ReadAll(FilePath path)
\r
124 #region private methods
\r
126 private void SetRow(DataRow row, string line)
\r
128 for (int i = 0; i < lineParser.Length; ++i)
\r
131 if (lineParser[i](ref line, out value))
\r
137 row.RowError = line;
\r
139 Match m = sepPattern.Match(line);
\r
140 line = line.Substring(m.Length);
\r
145 private void SetHeader(DataColumnCollection columns, string line)
\r
147 for (int i = 0; i < columns.Count; ++i)
\r
150 if (ParseString(ref line, out value))
\r
152 string name = value as string;
\r
153 Match comment = Regex.Match(name, @"^#\s*");
\r
154 columns[i].ColumnName = name.Substring(comment.Length);
\r
160 Match m = sepPattern.Match(line);
\r
161 line = line.Substring(m.Length);
\r
165 static private bool ParseDouble(ref string input, out object output)
\r
167 Match m = RegexSet.DecimalFloat.Match(input);
\r
173 output = Double.Parse(m.Groups[1].Value);
\r
174 input = input.Substring(m.Length);
\r
178 private bool ParseString(ref string input, out object output)
\r
180 Match quotedMatch = RegexSet.QuotedString.Match(input);
\r
181 if (quotedMatch.Success)
\r
183 string content = quotedMatch.Groups[1].Value;
\r
184 output = content.Replace("\"\"", "\"");
\r
185 input = input.Substring(quotedMatch.Length);
\r
189 Match m = sepPattern.Match(input);
\r
192 output = input.Substring(0, m.Index);
\r
193 input = input.Substring(m.Index);
\r
207 public class CsvReader<TDataSet> where TDataSet : IDataSet, new()
\r
209 private string separator = ",";
\r
216 /// <param name="path">CSVファイルのパス</param>
\r
217 /// <param name="proto">行の雛型</param>
\r
218 /// <returns>指定した型のリスト</returns>
\r
219 public List<TDataSet> Read(FilePath path)
\r
221 return Read(path, new TDataSet());
\r
225 /// 雛型を指定してCSVファイルを読み込む
\r
227 /// <param name="path">CSVファイルのパス</param>
\r
228 /// <param name="proto">行の雛型</param>
\r
229 /// <returns>指定した型のリスト</returns>
\r
230 public List<TDataSet> Read(FilePath path, TDataSet proto)
\r
232 List<TDataSet> records = new List<TDataSet>();
\r
236 //string regex = @"\s*" + RegexSet.DecimalFloat + @"\s*" + separator;
\r
237 string regex = @"\s*" + @"(?<1>([-+]?(\d+([\.,]\d*)?|([\.,]\d+))([eE][-+]?\d+)?))" + @"\s*" + separator;
\r
238 Regex rCsv = new Regex(regex, RegexOptions.Compiled);
\r
242 using (FileStream fs = new FileStream(
\r
243 path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
\r
245 using (StreamReader reader = new StreamReader(fs))
\r
247 while (reader.Peek() >= 0)
\r
249 line = reader.ReadLine() + separator;
\r
250 //Console.WriteLine("> " + line);
\r
251 MatchCollection mc = rCsv.Matches(line);
\r
253 // 現状ではNaNが含まれる行は受理しない
\r
254 if (!proto.Width.Includes(mc.Count)) continue;
\r
256 if (proto.KeyRange != null)
\r
258 double key = Double.Parse(mc[0].Groups[1].Value);
\r
259 if (!proto.KeyRange.Includes(key)) continue;
\r
262 TDataSet c = new TDataSet();
\r
263 foreach (Match m in mc)
\r
265 c.Push(Double.Parse(m.Groups[1].Value));
\r
272 catch (Exception e)
\r
274 Console.WriteLine("The file could not be read:");
\r
275 Console.WriteLine("> " + path);
\r
276 Console.WriteLine(e.Message);
\r