Incrementing Folder Names such as 5.0.0.x in C#
I have a folder ~/ConfigurationDirectory. The sub-folders within this开发者_如何学编程 folder are named as follows
5.0.0.1
5.0.0.2 5.0.0.3 ...Now, the requirement is that - Identify the folder which has the "largest" name numerically and create a copy of the folder. Rename the new folder as 5.0.0.n+1 (assuming that the largest numerically available folder is 5.0.0.n)
I have written code which will identify the largest named folder. Also, I have written the code which will do the copy of folder and sub-folders. What I am not able to get is, how do I get the name of the new folder, i.e., 5.0.0.n+1
How do I do this in C#? Any pointers would suffice rather than complete coding.
Thanks!
Assuming the numbers you're working with are not simple four-part version numbers, you're going to want to use the string.Split() to break up the folder name, and then Convert.ToInt32() or int.Parse() to turn the last chunk into a number. From there, you increment it, and then use something like string.Format() to turn it back into a folder name.
If, however, you are indeed working with simple version numbers, then using the System.Version
class (specifically, the Parse()
or TryParse()
and ToString()
methods) would be a significantly more straightforward implementation.
This is the most correct solution, imo:
Version version;
if (Version.TryParse("5.0.0.0", out version))
{
// your logic here
return new Version(
version.Major,
version.Minor,
version.Build,
version.Revision + 1).ToString();
// will return 5.0.0.1
}
else
{
// error handling here
}
You can use string.LastIndexOf
for this purpose (this is much more light-weight than using string.Split
):
static string GetNextFolderName(string folderName)
{
int lastDotPosition = folderName.LastIndexOf('.');
string lastPartOfFolderName = folderName.Substring(lastDotPosition + 1);
int number;
if (int.TryParse(lastPartOfFolderName, out number))
{
number++;
return folderName.Substring(0, lastDotPosition + 1) + number.ToString();
}
else
{
// You've got a problem on your hands, here.
throw new FormatException();
}
}
UPDATE: It has been pointed out that this approach is perhaps excessive in light of the existence of Version.TryParse
. A few points in response to that:
Version.TryParse
is available as of .NET 4.0. Many developers are not using .NET 4.0; therefore to discard any alternative approach right out is (in my opinion) quite narrow-sighted.- It has not been indicated whether performance is much of a concern. Presumably, it is not. However, when you think about the problem conceptually,
Version.TryParse
is actually doing significantly more work than we need in this case: it is looking at every individual component of the version string and parsing them all into a completeVersion
object. The approach outlined above, on the other hand, only bothers to examine the last part of the version string, and is therefore more efficient. I have verified this: using the approach above executes in about 30% of the time it takes usingVersion.TryParse
. - Of course it is fair to point out that, if one already knew of
Version.TryParse
and chose to write the above code anyway, one would be guilty of premature optimization. That said, suppose you did not know about it, and you already wrote the above code. Would the right thing to do be to refactor the code to useVersion.TryParse
, keeping the same functionality and slowing performance by about 200%? I'm not asking rhetorically; perhaps in some cases, for the sake of simplicity and maintainability, it might be. But it would be a judgment call.
I post these points primarily as a rebuttal to anyone who would immediately dismiss a solution simply because it performs the same task as an "out-of-the-box" solution. Sometimes, depending on your circumstances, it can make sense to do something yourself anyway. Just know what you're getting yourself into, and be ready to take a step back and change direction if and when it becomes appropriate to do so.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication1
{
static class Extensions
{
public static TOutput[] ToArray<TSource, TOutput>(this IEnumerable<TSource> col, Converter<TSource, TOutput> converter)
{
return Array.ConvertAll<TSource, TOutput>(col.ToArray(), converter);
}
}
class Program
{
static void Main(string[] args)
{
string original = "5.0.0.0";
int[] tmp = original.Split('.').ToArray<string, int>(new Converter<string, int>(delegate(string s)
{
int result;
return int.TryParse(s, out result) ? result : 0;
}));
tmp[tmp.Length - 1]++;
// re should contain 5.0.0.1
string re = String.Join(".", tmp);
}
}
}
It's a simple algorithm, which can be applied to any number of elements:
- Split the string on the dots. Call the resulting array
a
. - Convert the last element of a to an integer. Call this integer
i
. i++
a[last] = i.ToString()
- Join the elements of
a
using a dot as the separator.
Make sure that your identification algorithm really does select the numerically largest value: if you have 5.0.0.9 and 5.0.0.10, then you would find 5.0.0.9 if the identification really uses alphabetic ordering.
精彩评论