【发布时间】:2013-06-30 03:33:52
【问题描述】:
我正在管理一个文件目录。每个文件的命名类似于Image_000000.png,每个存储的文件的数字部分都会递增。
也可以删除文件,在数字序列中留下空白。我问的原因是因为我认识到在未来的某个时候,用户可能会用完数字序列,除非我采取措施在数字可用时重用它们。我知道它是一百万,而且很多,但我们有 20 多年的用户,所以“总有一天”不是不可能的。
所以,我特意询问是否存在一种无需简单循环即可轻松确定序列间隙的方法。我意识到,因为它是一个固定范围,我可以简单地循环预期的范围。
除非有更好/更清洁/更容易/更快的替代方案,否则我会这样做。如果是这样,我想知道。
调用该方法获取下一个可用的文件名:
public static String GetNextImageFileName()
{
String retFile = null;
DirectoryInfo di = new DirectoryInfo(userVars.ImageDirectory);
FileInfo[] fia = di.GetFiles("*.*", SearchOption.TopDirectoryOnly);
String lastFile = fia.Where(i => i.Name.StartsWith("Image_") && i.Name.Substring(6, 6).ContainsOnlyDigits()).OrderBy(i => i.Name).Last().Name;
if (!String.IsNullOrEmpty(lastFile))
{
Int32 num;
String strNum = lastFile.Substring(6, 6);
String strExt = lastFile.Substring(13);
if (!String.IsNullOrEmpty(strNum) &&
!String.IsNullOrEmpty(strExt) &&
strNum.ContainsOnlyDigits() &&
Int32.TryParse(strNum, out num))
{
num++;
retFile = String.Format("Image_{0:D6}.{1}", num, strExt);
while (num <= 999999 && File.Exists(retFile))
{
num++;
retFile = String.Format("Image_{0:D6}.{1}", num, strExt);
}
}
}
return retFile;
}
编辑:如果它对任何人有帮助,这是最后的方法,结合 Daniel Hilgarth 的回答:
public static String GetNextImageFileName()
{
DirectoryInfo di = new DirectoryInfo(userVars.ImageDirectory);
FileInfo[] fia = di.GetFiles("Image_*.*", SearchOption.TopDirectoryOnly);
List<Int32> fileNums = new List<Int32>();
foreach (FileInfo fi in fia)
{
Int32 i;
if (Int32.TryParse(fi.Name.Substring(6, 6), out i))
fileNums.Add(i);
}
var result = fileNums.Select((x, i) => new { Index = i, Value = x })
.Where(x => x.Index != x.Value)
.Select(x => (Int32?)x.Index)
.FirstOrDefault();
Int32 index;
if (result == null)
index = fileNums.Count - 1;
else
index = result.Value - 1;
var nextNumber = fileNums[index] + 1;
if (nextNumber >= 0 && nextNumber <= 999999)
return String.Format("Image_{0:D6}", result.Value);
return null;
}
【问题讨论】:
-
您真的需要增加数字,还是只需要唯一的文件名?获取唯一文件名的方法比您使用的方法更简单。
-
@Servy 你的意思是像
Path.GetTempFileName()这样的东西吗?我考虑过这个选项,但我需要确保用户可以在必要时在我们的应用程序之外找到文件,所以我选择了“平均乔”更易读的东西。 -
只需在前面粘贴
yymmdd格式的日期即可。如果您还将 6 位数字附加到日期,则可以在到达 999999 时将数字换行。除非您在一天内创建超过 999999 个文件,否则不会给您带来任何冲突。 (它会在 2099 年给你带来麻烦,但你可能不会太担心...... ;) -
这实际上正是我的想法,但即使你确实想要一些更具可读性的东西,你也有更好的选择。例如,将创建的时间戳附加到问题的末尾(只要确保有足够的精度以确保仍然没有重复并处理由于夏令时而出现的重复情况(可能通过使用没有 DST 的位置))。除了这些之外,还有其他选项仍然比你拥有的更容易处理,我的问题仍然是,它们是一个选项,还是你必须使用这个系统?
-
10,000,000 个文件仍然没有问题吗?还是一亿?换句话说:只需增加您使用的位数,直到您可以确定不会出现回绕。
标签: c# linq .net-3.5 sequences