From e8be38721a7de7884ea5c983db7feddb5f6fe26c Mon Sep 17 00:00:00 2001 From: kimikage Date: Wed, 19 Oct 2011 20:44:34 +0900 Subject: [PATCH] =?utf8?q?CsvWriter=E3=81=AE=E8=BF=BD=E5=8A=A0(#23890)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- Karinto/CsvWriter.cs | 329 +++++++++++++++++++++++++++++++++++++++++ Karinto/Karinto.csproj | 1 + KarintoTest/CsvWriterTest.cs | 149 +++++++++++++++++++ KarintoTest/KarintoTest.csproj | 1 + 4 files changed, 480 insertions(+) create mode 100755 Karinto/CsvWriter.cs create mode 100755 KarintoTest/CsvWriterTest.cs diff --git a/Karinto/CsvWriter.cs b/Karinto/CsvWriter.cs new file mode 100755 index 0000000..9216077 --- /dev/null +++ b/Karinto/CsvWriter.cs @@ -0,0 +1,329 @@ +/* + * Karinto Library Project + * + * This software is distributed under a zlib-style license. + * See license.txt for more information. + */ + +using System; +using System.IO; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; +using System.Data; + +namespace Karinto +{ + public class CsvWriter : CsvWriter + { + private CsvWriter() + { + } + + public CsvWriter(DataTable prototype) + : base(prototype) + { + } + } + + public class CsvWriter where TDataTable : DataTable, new() + { + #region type definitions + public delegate string Formatter(object input); + #endregion + + #region private fields + + private string separator; + private Regex stringToBeQuoted; + private TDataTable prototype; + private DataColumnCollection cols; + + private static Dictionary formatters; + private Formatter[] lineFormatter; + private bool[] userDefined; + + #endregion + + #region constructors + static CsvWriter() + { + formatters = new Dictionary(); + formatters[typeof(Boolean)] = FormatBoolean; + formatters[typeof(Double)] = FormatDouble; + formatters[typeof(Single)] = FormatSingle; + formatters[typeof(Decimal)] = FormatDecimal; + formatters[typeof(Int32)] = FormatInt32; + formatters[typeof(Int64)] = FormatInt64; + } + + public CsvWriter() + : this(new TDataTable()) + { + } + + public CsvWriter(TDataTable prototype) + { + Separator = @","; + this.prototype = (TDataTable)prototype.Clone(); + cols = prototype.Columns; + lineFormatter = new Formatter[cols.Count]; + for (int i = 0; i < cols.Count; ++i) + { + Type t = cols[i].DataType; + if (formatters[t] != null) + { + lineFormatter[i] = formatters[t]; + } + else if (t == typeof(DateTime)) + { + lineFormatter[i] = FormatDateTime; + } + else + { + lineFormatter[i] = FormatString; + } + } + } + + public CsvWriter(FilePath path) + { + + } + #endregion + + #region properties + + /// + /// 区切り文字 + /// + public string Separator + { + get + { + return separator; + } + set + { + separator = value; + stringToBeQuoted = new Regex(@"(?:[\""]|" + value + ")"); + } + } + + #endregion + + #region public methods + + public void Write(FilePath path, TDataTable table) + { + try + { + using (FileStream fs = new FileStream(path, + FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)) + { + using (StreamWriter writer = new StreamWriter(fs)) + { + WriteBody(table, writer); + } + } + } + catch (Exception ex) + { + throw ex; + } + } + + public void WriteWithCaption(FilePath path, TDataTable table) + { + try + { + using (FileStream fs = new FileStream(path, + FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)) + { + using (StreamWriter writer = new StreamWriter(fs)) + { + WriteCaption(table, writer); + WriteBody(table, writer); + } + } + } + catch (Exception ex) + { + throw ex; + } + } + + public Formatter GetFormatter(int column) + { + return lineFormatter[column]; + } + + public Formatter GetFormatter(string column) + { + return lineFormatter[prototype.Columns.IndexOf(column)]; + } + + public Formatter GetFormatter(DataColumn column) + { + return lineFormatter[prototype.Columns.IndexOf(column.ColumnName)]; + } + + public static Formatter GetFormatter(Type type) + { + return formatters[type]; + } + + public void SetFormatter(int column, Formatter formatter) + { + lineFormatter[column] = formatter; + } + + public void SetFormatter(string column, Formatter formatter) + { + lineFormatter[prototype.Columns.IndexOf(column)] = formatter; + } + + public void SetFormatter(DataColumn column, Formatter formatter) + { + lineFormatter[prototype.Columns.IndexOf(column.ColumnName)] + = formatter; + } + + public static void SetParser(Type type, Formatter formatter) + { + formatters[type] = formatter; + } + + + #endregion + + #region private methods + + private void WriteBody(TDataTable table, StreamWriter writer) + { + int n = table.Rows.Count; + int col = table.Columns.Count - 1; + StringBuilder builder = new StringBuilder(); + + for (int row = 0; row < n; ++row) + { + builder.Remove(0, builder.Length); + DataRow r = table.Rows[row]; + for (int i = 0; i < col; ++i) + { + builder.Append(lineFormatter[i](r[i])); + builder.Append(separator); + } + builder.Append(lineFormatter[col](r[col])); + string line = builder.ToString(); + writer.WriteLine(line); + } + } + + private void WriteCaption(TDataTable table, StreamWriter writer) + { + int col = table.Columns.Count; + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < col; ++i) + { + builder.Append(FormatString(table.Columns[i].Caption)); + builder.Append(separator); + } + writer.WriteLine(builder.ToString()); + } + + private void SetLineFormatter() + { + cols = prototype.Columns; + int n = cols.Count; + if (lineFormatter == null) + { + lineFormatter = new Formatter[n]; + userDefined = new bool[n]; + } + for (int i = 0; i < n; ++i) + { + Type t = cols[i].DataType; + if (userDefined[i] && lineFormatter[i] != null) + { + continue; + } + if (formatters.ContainsKey(t)) + { + lineFormatter[i] = formatters[t]; + continue; + } + if (t == typeof(Double)) + { + lineFormatter[i] = FormatDouble; + } + else if (t == typeof(Single)) + { + lineFormatter[i] = FormatSingle; + } + else if (t == typeof(Decimal)) + { + lineFormatter[i] = FormatDecimal; + } + else if (t == typeof(DateTime)) + { + lineFormatter[i] = FormatDateTime; + } + else + { + lineFormatter[i] = FormatString; + } + } + } + + #region formatters + + private static string FormatBoolean(object input) + { + return input.ToString(); + } + + private static string FormatDouble(object input) + { + return ((double)input).ToString("r"); + } + + private static string FormatSingle(object input) + { + return ((float)input).ToString("r"); + } + + private static string FormatDecimal(object input) + { + return ((decimal)input).ToString("g"); + } + + private static string FormatInt32(object input) + { + return ((Int32)input).ToString("g"); + } + + private static string FormatInt64(object input) + { + return ((Int64)input).ToString("g"); + } + + private string FormatDateTime(object input) + { + return ((DateTime)input).ToString("u"); + } + + private string FormatString(object input) + { + string s = input.ToString(); + if (stringToBeQuoted.IsMatch(s)) + { + return "\"" + s.Replace("\"","\"\"") + "\""; + } + return s; + } + #endregion + + #endregion + } +} diff --git a/Karinto/Karinto.csproj b/Karinto/Karinto.csproj index 2d62e6c..b9afde1 100755 --- a/Karinto/Karinto.csproj +++ b/Karinto/Karinto.csproj @@ -41,6 +41,7 @@ + diff --git a/KarintoTest/CsvWriterTest.cs b/KarintoTest/CsvWriterTest.cs new file mode 100755 index 0000000..c5fdfcc --- /dev/null +++ b/KarintoTest/CsvWriterTest.cs @@ -0,0 +1,149 @@ +/* + * Karinto Library Project + * + * This software is distributed under a zlib-style license. + * See license.txt for more information. + */ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.Data; +using System.IO; +using Karinto; +using Karinto.Xml; +using NUnit.Framework; + +namespace KarintoTest +{ + [TestFixture] + public class CsvWriterTest + { + + [Test] + public void XY2chData() + { + File.Delete("Resources/d_d_d_out.csv"); + + CsvReader reader = + new CsvReader(); + Data.XY2ChDataTable source = reader.Read("Resources/d_d_d.csv"); + + CsvWriter writer = + new CsvWriter(); + writer.Write("Resources/d_d_d_out.csv", source); + + Data.XY2ChDataTable table = reader.Read("Resources/d_d_d_out.csv"); + + Assert.AreEqual("X", table.XColumn.Caption); + Assert.AreEqual("Y1", table.Y1Column.Caption); + Assert.AreEqual("Y2", table.Y2Column.Caption); + + Assert.AreEqual(0.0, table[0].X); + Assert.AreEqual(5.0, table[50].X); + Assert.AreEqual(10.0, table[100].X); + + Assert.AreEqual(0.0, table[0].Y1); + Assert.AreEqual(0.0, table[50].Y1); + Assert.AreEqual(0.0, table[100].Y1); + + Assert.AreEqual(0.0, table[0].Y2); + Assert.AreEqual(1.0, table[50].Y2); + Assert.AreEqual(0.0, table[100].Y2); + + } + + [Test] + public void XY2chDataWithCaption() + { + File.Delete("Resources/d_d_d_out.csv"); + + CsvReader reader = + new CsvReader(); + Data.XY2ChDataTable source = reader.Read("Resources/d_d_d.csv"); + + CsvWriter writer = + new CsvWriter(); + writer.WriteWithCaption("Resources/d_d_d_out.csv", source); + + Data.XY2ChDataTable table = reader.Read("Resources/d_d_d_out.csv"); + + Assert.AreEqual("Header1", table.XColumn.Caption); + Assert.AreEqual("Header2", table.Y1Column.Caption); + Assert.AreEqual("Header3", table.Y2Column.Caption); + + Assert.AreEqual(0.0, table[0].X); + Assert.AreEqual(5.0, table[50].X); + Assert.AreEqual(10.0, table[100].X); + + Assert.AreEqual(0.0, table[0].Y1); + Assert.AreEqual(0.0, table[50].Y1); + Assert.AreEqual(0.0, table[100].Y1); + + Assert.AreEqual(0.0, table[0].Y2); + Assert.AreEqual(1.0, table[50].Y2); + Assert.AreEqual(0.0, table[100].Y2); + + } + + [Test] + public void XY1chData() + { + File.Delete("Resources/d_d_d_out.csv"); + + CsvReader reader = + new CsvReader(); + Data.XY1ChDataTable table = reader.Read("Resources/d_d_d.csv"); + + Assert.AreEqual("Header1", table.XColumn.Caption); + Assert.AreEqual("Header2", table.YColumn.Caption); + + Assert.AreEqual(0.0, table[0].X); + Assert.AreEqual(5.0, table[50].X); + Assert.AreEqual(10.0, table[100].X); + + Assert.AreEqual(0.0, table[0].Y); + Assert.AreEqual(0.0, table[50].Y); + Assert.AreEqual(0.0, table[100].Y); + } + + [Test] + public void Prototype() + { + + File.Delete("Resources/d_d_d_out.csv"); + + DataTable prototype = new DataTable(); + prototype.Columns.Add("X", typeof(decimal)); + prototype.Columns.Add("Y1", typeof(float)); + prototype.Columns.Add("Y2", typeof(int)); + + CsvReader reader = new CsvReader(prototype); + DataTable source = reader.Read("Resources/d_d_d.csv"); + + CsvWriter writer = new CsvWriter(prototype); + prototype = null; + + writer.WriteWithCaption("Resources/d_d_d_out.csv", source); + + DataTable table = reader.Read("Resources/d_d_d.csv"); + + Assert.AreEqual("Header1", table.Columns["X"].Caption); + Assert.AreEqual("Header2", table.Columns["Y1"].Caption); + Assert.AreEqual("Header3", table.Columns["Y2"].Caption); + + Assert.AreEqual(0.0m, table.Rows[0]["X"]); + Assert.AreEqual(5.0m, table.Rows[50]["X"]); + Assert.AreEqual(10.0m, table.Rows[100]["X"]); + + Assert.AreEqual(0.0f, table.Rows[0]["Y1"]); + Assert.AreEqual(0.0f, table.Rows[50]["Y1"]); + Assert.AreEqual(0.0f, table.Rows[100]["Y1"]); + + Assert.AreEqual(0, table.Rows[0]["Y2"]); + Assert.AreEqual(1, table.Rows[50]["Y2"]); + Assert.AreEqual(0, table.Rows[100]["Y2"]); + } + } +} diff --git a/KarintoTest/KarintoTest.csproj b/KarintoTest/KarintoTest.csproj index 99d8796..d37c51c 100755 --- a/KarintoTest/KarintoTest.csproj +++ b/KarintoTest/KarintoTest.csproj @@ -51,6 +51,7 @@ + -- 2.11.0