OSDN Git Service

CSVの読み込みでデリミタと小数点の区別が正しく行われなかった不具合を修正
authorkimikage <kimikage_ceo@hotmail.com>
Wed, 19 Oct 2011 03:57:20 +0000 (12:57 +0900)
committerkimikage <kimikage_ceo@hotmail.com>
Wed, 19 Oct 2011 10:26:30 +0000 (19:26 +0900)
Karinto/CsvReader.cs

index 7033ea2..8b33cb5 100755 (executable)
@@ -38,6 +38,7 @@ namespace Karinto
         public delegate bool Parser(ref string input, out object output);\r
         private static Dictionary<Type, Parser> parsers;\r
         private Parser[] lineParser;\r
+        private bool[] userDefined;\r
 \r
         #endregion\r
 \r
@@ -46,9 +47,6 @@ namespace Karinto
         {\r
             parsers = new Dictionary<Type, Parser>();\r
             parsers[typeof(Boolean)] = ParseBoolean;\r
-            parsers[typeof(Double)] = ParseDouble;\r
-            parsers[typeof(Single)] = ParseSingle;\r
-            parsers[typeof(Decimal)] = ParseDecimal;\r
             parsers[typeof(Int32)] = ParseInt32;\r
             parsers[typeof(Int64)] = ParseInt64;\r
         }\r
@@ -62,24 +60,7 @@ namespace Karinto
         {\r
             Separator = @",";\r
             this.prototype = (TDataTable)prototype.Clone();\r
-            cols = prototype.Columns;\r
-            lineParser = new Parser[cols.Count];\r
-            for (int i = 0; i < cols.Count; ++i)\r
-            {\r
-                Type t = cols[i].DataType;\r
-                if (parsers[t] != null)\r
-                {\r
-                    lineParser[i] = parsers[t];\r
-                }\r
-                else if (t == typeof(DateTime))\r
-                {\r
-                    lineParser[i] = ParseDateTime;\r
-                }\r
-                else\r
-                {\r
-                    lineParser[i] = ParseString;\r
-                }\r
-            }\r
+            SetLineParser();\r
         }\r
         #endregion\r
 \r
@@ -193,19 +174,20 @@ namespace Karinto
         public void SetParser(int column, Parser parser)\r
         {\r
             lineParser[column] = parser;\r
+            userDefined[column] = parser != null;\r
         }\r
 \r
         public void SetParser(string column, Parser parser)\r
         {\r
-            lineParser[prototype.Columns.IndexOf(column)] = parser;\r
+            SetParser(prototype.Columns.IndexOf(column), parser);\r
         }\r
 \r
         public void SetParser(DataColumn column, Parser parser)\r
         { \r
-            lineParser[prototype.Columns.IndexOf(column.ColumnName)] = parser;\r
+            SetParser(prototype.Columns.IndexOf(column.ColumnName),parser);\r
         }\r
 \r
-        public static void SetParser(Type type, Parser parser)\r
+        public static void SetDefaultParser(Type type, Parser parser)\r
         {\r
             parsers[type] = parser;\r
         }\r
@@ -265,6 +247,50 @@ namespace Karinto
             return;\r
         }\r
 \r
+        private void SetLineParser()\r
+        {\r
+            cols = prototype.Columns;\r
+            int n = cols.Count;\r
+            if (lineParser == null)\r
+            {\r
+                lineParser = new Parser[n];\r
+                userDefined = new bool[n];\r
+            }\r
+            for (int i = 0; i < n; ++i)\r
+            {\r
+                Type t = cols[i].DataType;\r
+                if (userDefined[i] && lineParser[i] != null)\r
+                {\r
+                    continue;\r
+                }\r
+                if (parsers.ContainsKey(t))\r
+                {\r
+                    lineParser[i] = parsers[t];\r
+                    continue;\r
+                }\r
+                if (t == typeof(Double))\r
+                {\r
+                    lineParser[i] = ParseDouble;\r
+                }\r
+                else if (t == typeof(Single))\r
+                {\r
+                    lineParser[i] = ParseSingle;\r
+                }\r
+                else if (t == typeof(Decimal))\r
+                {\r
+                    lineParser[i] = ParseDecimal;\r
+                }\r
+                else if (t == typeof(DateTime))\r
+                {\r
+                    lineParser[i] = ParseDateTime;\r
+                }\r
+                else\r
+                {\r
+                    lineParser[i] = ParseString;\r
+                }\r
+            }\r
+        }\r
+\r
         #region parsers\r
 \r
         private static bool ParseBoolean(ref string input, out object output)\r
@@ -286,7 +312,7 @@ namespace Karinto
             return true;\r
         }\r
 \r
-        private static bool ParseDouble(ref string input, out object output)\r
+        private bool ParseDouble(ref string input, out object output)\r
         {\r
             Match m = RegexSet.DecimalFloat.Match(input);\r
             if (!m.Success)\r
@@ -294,12 +320,18 @@ namespace Karinto
                 output = 0;\r
                 return false;\r
             }\r
-            output = Double.Parse(m.Groups[1].Value);\r
-            input = input.Substring(m.Length);\r
+            string matched = m.Groups[1].Value;\r
+            m = sepPattern.Match(matched);\r
+            if (m.Success)\r
+            {\r
+                matched = matched.Substring(0, m.Index);\r
+            }\r
+            output = Double.Parse(matched);\r
+            input = input.Substring(matched.Length);\r
             return true;\r
         }\r
 \r
-        private static bool ParseSingle(ref string input, out object output)\r
+        private bool ParseSingle(ref string input, out object output)\r
         {\r
             Match m = RegexSet.DecimalFloat.Match(input);\r
             if (!m.Success)\r
@@ -307,12 +339,18 @@ namespace Karinto
                 output = 0;\r
                 return false;\r
             }\r
-            output = Single.Parse(m.Groups[1].Value);\r
-            input = input.Substring(m.Length);\r
+            string matched = m.Groups[1].Value;\r
+            m = sepPattern.Match(matched);\r
+            if (m.Success)\r
+            {\r
+                matched = matched.Substring(0, m.Index);\r
+            }\r
+            output = Single.Parse(matched);\r
+            input = input.Substring(matched.Length);\r
             return true;\r
         }\r
 \r
-        private static bool ParseDecimal(ref string input, out object output)\r
+        private bool ParseDecimal(ref string input, out object output)\r
         {\r
             Match m = RegexSet.DecimalFloat.Match(input);\r
             if (!m.Success)\r
@@ -320,8 +358,14 @@ namespace Karinto
                 output = 0;\r
                 return false;\r
             }\r
-            output = Decimal.Parse(m.Groups[1].Value);\r
-            input = input.Substring(m.Length);\r
+            string matched = m.Groups[1].Value;\r
+            m = sepPattern.Match(matched);\r
+            if (m.Success)\r
+            { \r
+                matched = matched.Substring(0, m.Index);\r
+            }\r
+            output = Decimal.Parse(matched);\r
+            input = input.Substring(matched.Length);\r
             return true;\r
         }\r
 \r