如何控制DataTable转CSV toString()格式?
How to control DataTable to CSV toString() formatting?
我有一个小应用程序在我的机器上运行良好,我能够从 MySQL 数据库中获取数据到 DataTable,然后毫无问题地将 DataTable 写入 CSV,然后有人试图 运行 这在他们的机器上和日期时间列开始有与预期不同的行为:
在我的机器上我有这样的东西:(这就是我想要的)
2015-11-14 00:00:00,
2015-11-14 00:01:00,
2015-11-14 00:02:00,
2015-11-14 00:03:00,
但是在另一台机器上我有:
15/07/2015 4:40:55 PM,
15/07/2015 4:41:56 PM,
15/07/2015 4:42:55 PM,
15/07/2015 4:43:55 PM,
15/07/2015 4:44:56 PM,
我的代码是:
try
{
lock (writtingLock)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-CA");
dataTable = newMyDataTable;
fileId = dataTable.TableName;
PathMaker path = new PathMaker(fileId);
path.Make();
// writing the table to a file
using (StreamWriter swr =
new StreamWriter(File.Open(path.filePath, FileMode.Create), Encoding.Default, 1000000))
// change buffer size and Encoding to your needs
{
if (addHeader)
{
foreach (var dc in dataTable.Columns)
{
swr.Write(dc.ToString() + ",");
}
swr.WriteLine();
}
foreach (DataRow dr in dataTable.Rows)
{
Object[] test = dr.ItemArray;
test.Where(o => o.GetType() == typeof(DateTime)).Select(t => (DateTime)t).Select(x => x.ToFileTime());
swr.WriteLine(string.Join(",", test.Select(x => x.ToString().TrimEnd(null)).ToArray()));
}
}
}
}
添加或删除 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-CA");
没有效果,我该如何解决这个问题?有没有办法控制格式?
使用DateTime::ToString("o", CultureInfo.InvariantCulture )
.
这一行:
swr.WriteLine(string.Join(",", test.Select(x => x.ToString().TrimEnd(null)).ToArray()));
查看x.ToString()
表达式。
.Net 使用重载解析来知道它需要调用 DateTime.ToString()
。此方法的文档包括以下内容:
This method uses formatting information derived from the current culture. In particular, it combines the custom format strings returned by the ShortDatePattern and LongTimePattern
换句话说,另一台计算机的日期格式设置选项与您的不同。
您开始通过在代码的前面设置线程区域性来解决这个问题。但是,如果我将我自己的系统设置为使用 en-CA
文化,然后还在我的机器上自定义 date/time 格式,将 en-CA
文化应用到线程仍然使用我的自定义日期 -时间格式,因为这就是我所说的 en-CA
在这个系统上应该是这样的。
您可能不喜欢它,但这是非常正常的事情,作为程序员,我们应该在需要精确格式化时提前考虑。看起来您确实需要精确的格式,您需要调整此代码以使其足够智能以了解日期类型与其他类型之间的区别,以便您可以指定所需的精确格式。
您需要对数字类型执行相同的操作(int
、float
、decimal
、single
、double
等) ,因为这些类型的输出也可能因系统当前的区域性设置而异。
只有一种捷径。您可以使用 InvariantCulture
。但是,这仅在 InvariantCulture 恰好具有您想要的格式时才有效。如果您需要不同的东西,您将返回处理单个类型。不过,有时 InvariantCulture 可能是一个有用的起点。例如,对于数字可能是正确的,这样您只需提供日期格式。
最后,当我在这里的时候,我想调用前面的代码行:
test.Where(o => o.GetType() == typeof(DateTime)).Select(t => (DateTime)t).Select(x => x.ToFileTime());
该代码无效!它不会分配回您的 test
变量,因此它所做的任何工作(谢天谢地,不是很多,因为枚举器永远不会被执行)只会被扔掉。您可能应该只删除这一行。
我有一个小应用程序在我的机器上运行良好,我能够从 MySQL 数据库中获取数据到 DataTable,然后毫无问题地将 DataTable 写入 CSV,然后有人试图 运行 这在他们的机器上和日期时间列开始有与预期不同的行为: 在我的机器上我有这样的东西:(这就是我想要的)
2015-11-14 00:00:00,
2015-11-14 00:01:00,
2015-11-14 00:02:00,
2015-11-14 00:03:00,
但是在另一台机器上我有:
15/07/2015 4:40:55 PM,
15/07/2015 4:41:56 PM,
15/07/2015 4:42:55 PM,
15/07/2015 4:43:55 PM,
15/07/2015 4:44:56 PM,
我的代码是:
try
{
lock (writtingLock)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-CA");
dataTable = newMyDataTable;
fileId = dataTable.TableName;
PathMaker path = new PathMaker(fileId);
path.Make();
// writing the table to a file
using (StreamWriter swr =
new StreamWriter(File.Open(path.filePath, FileMode.Create), Encoding.Default, 1000000))
// change buffer size and Encoding to your needs
{
if (addHeader)
{
foreach (var dc in dataTable.Columns)
{
swr.Write(dc.ToString() + ",");
}
swr.WriteLine();
}
foreach (DataRow dr in dataTable.Rows)
{
Object[] test = dr.ItemArray;
test.Where(o => o.GetType() == typeof(DateTime)).Select(t => (DateTime)t).Select(x => x.ToFileTime());
swr.WriteLine(string.Join(",", test.Select(x => x.ToString().TrimEnd(null)).ToArray()));
}
}
}
}
添加或删除 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-CA");
没有效果,我该如何解决这个问题?有没有办法控制格式?
使用DateTime::ToString("o", CultureInfo.InvariantCulture )
.
这一行:
swr.WriteLine(string.Join(",", test.Select(x => x.ToString().TrimEnd(null)).ToArray()));
查看x.ToString()
表达式。
.Net 使用重载解析来知道它需要调用 DateTime.ToString()
。此方法的文档包括以下内容:
This method uses formatting information derived from the current culture. In particular, it combines the custom format strings returned by the ShortDatePattern and LongTimePattern
换句话说,另一台计算机的日期格式设置选项与您的不同。
您开始通过在代码的前面设置线程区域性来解决这个问题。但是,如果我将我自己的系统设置为使用 en-CA
文化,然后还在我的机器上自定义 date/time 格式,将 en-CA
文化应用到线程仍然使用我的自定义日期 -时间格式,因为这就是我所说的 en-CA
在这个系统上应该是这样的。
您可能不喜欢它,但这是非常正常的事情,作为程序员,我们应该在需要精确格式化时提前考虑。看起来您确实需要精确的格式,您需要调整此代码以使其足够智能以了解日期类型与其他类型之间的区别,以便您可以指定所需的精确格式。
您需要对数字类型执行相同的操作(int
、float
、decimal
、single
、double
等) ,因为这些类型的输出也可能因系统当前的区域性设置而异。
只有一种捷径。您可以使用 InvariantCulture
。但是,这仅在 InvariantCulture 恰好具有您想要的格式时才有效。如果您需要不同的东西,您将返回处理单个类型。不过,有时 InvariantCulture 可能是一个有用的起点。例如,对于数字可能是正确的,这样您只需提供日期格式。
最后,当我在这里的时候,我想调用前面的代码行:
test.Where(o => o.GetType() == typeof(DateTime)).Select(t => (DateTime)t).Select(x => x.ToFileTime());
该代码无效!它不会分配回您的 test
变量,因此它所做的任何工作(谢天谢地,不是很多,因为枚举器永远不会被执行)只会被扔掉。您可能应该只删除这一行。