我对c#编程很新,所以如果我的问题很简单,我会道歉。 我正在运行一些c#代码,我需要迭代文件夹中的一些文件并使用:
foreach (string f in Directory.GetFiles(@"C:\temp\GeneralStats"))
{
但是,我想根据文件名以特定顺序读取这些文件。我的文件名格式如下。
generalstats_2012_11_1.csv generalstats_2012_11_2.csv generalstats_2012_11_3.csv .....
当我的代码读入文件时,它会以generalstats_2012_11_1.csv开头,但会直接跳转到generalstats_2012_11_10.csv,而不是generalstats_2012_11_2.csv。
我尝试在网上搜索答案,但一直找不到。我当然按照特定文件夹中的日期(名称)命令文件,但代码根本不承认。 任何人都可以帮助我 - 我错过了c#中的一些订单功能吗?
答案 0 :(得分:2)
您可以使用:
var paths = Directory.GetFiles(@"C:\temp\GeneralStats")
.OrderBy(path =>
Convert.ToInt32(path.Split('_', '.')[1]) * 10000 +
Convert.ToInt32(path.Split('_', '.')[2]) * 100 +
Convert.ToInt32(path.Split('_', '.')[3]));
foreach (string path in paths)
{
}
这从文件名中获取日期部分并从中创建一个整数,例如文件名中的2012_11_10
为2012110为整数,2012_11_1
为20121101等。这些数字用于排序
上述方法的另一种变体是:
var paths = Directory.GetFiles(@"C:\temp\GeneralStats")
.OrderBy(path =>
Convert.ToInt32(
String.Concat(
path.Split('_', '.')
.Skip(1)
.Take(3)
.Select(num => num.PadLeft(2, '0'))
.ToArray())
)
);
它还解析文件名中的数字并创建用于排序的整数。
您可以使用Directory.GetFiles
代替Directory.EnumerateFiles
方法(但这仅适用于.NET 4及更高版本)。
答案 1 :(得分:2)
如果您想按文件名后面的日期订购,则必须将其转换为一个,否则订单按字母顺序排列(因此“10”在“2”之前)。
您可以在此linq查询中使用Enumerable.OrderBy
:
var files = Directory.EnumerateFiles(@"C:\temp\GeneralStats", "*.csv")
.Select(fn => new
{
Path = fn,
Split = Path.GetFileNameWithoutExtension(fn).Split('_')
})
.Where(x => x.Split.Length == 4)
.Select(x => new
{
x.Path,
Date = new DateTime(int.Parse(x.Split[1]), int.Parse(x.Split[2]), int.Parse(x.Split[3]))
})
.OrderBy(x => x.Date)
.Select(x => x.Path);
首先,我选择的匿名类型包含Path
类中的一些有用属性,例如GetFileNameWithoutExtension
。这将使查询的其余部分更有效,更可读。 Where
用于防止文件名中没有日期部分的文件时出错。下一个select从DateTime
派生的标记中解析string.Split
。最后三部分包含年,月和日。 OrderBy
将按日期排序。最后,我再次选择完整路径,因为您最初想要订购文件。
您可以使用foreach
枚举结果或使用例如ToList
如果你想坚持下去:
foreach (string f in files)
{
// ...
}