Splitting a filename

2019-06-22 13:43发布

问题:

I've a filename:

NewReport-20140423_17255375-BSIQ-2wd28830-841c-4d30-95fd-a57a7aege412.zip

How can i split the above filename to 4 string groups.

NewReport
20140423_17255375
BSIQ
2wd28830-841c-4d30-95fd-a57a7aege412.zip

I tried:

 string[] strFileTokens = filename.Split(new char[]{'-'} , StringSplitOptions.None);

but i'm not getting the above required four strings

回答1:

You can specify the maximum number of substrings to return:

var strFileTokens = filename.Split(new[] { '-' }, 4, StringSplitOptions.None);

This will avoid splitting 2wd28830-841c-4d30-95fd-a57a7aege412.zip into additional "pieces".

(Also, you can drop StringSplitOptions.None since that's the default.)


Internally, it creates an array of substrings inside a loop, and it only loops the number of times you specify (or the maximum number of delimiters available in your string, whichever is less).

for (int i = 0; i < numActualReplaces && currIndex < Length; i++)
{
    splitStrings[arrIndex++] = Substring(currIndex, sepList[i] - currIndex );
    currIndex = sepList[i] + ((lengthList == null) ? 1 : lengthList[i]); 
}

The variable numActualReplaces is the minimum of either the count you specify, or the number of actual delimiters present in your string. (That way, if you specify a larger number like 30, but you only have 7 hyphens in the string, you won't get an exception. Actually, when you don't specify a number at all, it's actually using Int32.MaxValue without you even realizing it.)


You updated your question to say you're using Silverlight, which doesn't have he overloads with Count. That's really annoying, because under the hood the string class still supports it. They just didn't provide a way to pass in your own value. It uses a hard-coded int.MaxValue.

You could create your own method to bring back the desired functionality. I haven't tested this extension method out for all edge-cases, but it does work with your string.

public static class StringSplitExtension
{
    public static string[] SplitByCount(this string input, char[] separator, int count)
    {
        if (count < 0)
            throw new ArgumentOutOfRangeException("count");

        if (count == 0)
            return new string[0];

        var numberOfSeparators = input.Count(separator.Contains);

        var numActualReplaces = Math.Min(count, numberOfSeparators + 1);

        var splitString = new string[numActualReplaces];

        var index = -1;
        for (var i = 1; i <= numActualReplaces; i++)
        {
            var nextIndex = input.IndexOfAny(separator, index + 1);
            if (nextIndex == -1 || i == numActualReplaces)
                splitString[i - 1] = input.Substring(index + 1);
            else
                splitString[i - 1] = input.Substring(index + 1, nextIndex - index - 1);
            index = nextIndex;
        }

        return splitString;
    }
}

Make sure it's somewhere accessible to your UserControl, then call it like this:

var strFileTokens = filename.SplitByCount(new[] { '-' }, 4)


回答2:

It works if you call the overload of Split that takes a count parameter:

var myArray = filename.Split(new char[] { '-' }, 4);


回答3:

Since you're using silverlight as shown in your follow up question which doesn't have this overload i show a different approach. You could use LINQ's Skip, Take + string.Join to get one string:

Your sample string:

string filename = "NewReport-20140423_17255375-BSIQ-2wd28830-841c-4d30-95fd-a57a7aege412.zip";

An array with all parts:

string[] allTokens = filename.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries);

var firstThreeToken = allTokens.Take(3);  // first three
var lastTokens = allTokens.Skip(3);       // the last part 
string lastToken = string.Join("-", lastTokens); // last tokens as single string
string[] allToken = firstThreeToken.Concat(new[] { lastToken }).ToArray();

Result:

"NewReport" 
"20140423_17255375"
"BSIQ"
"2wd28830-841c-4d30-95fd-a57a7aege412.zip"  


回答4:

You can use the Regex.Split method which offers an overload that takes the count param.

Regex reg = new Regex( "-" );
string filename = "NewReport-20140423_17255375-BSIQ-2wd28830-841c-4d30-95fd-a57a7aege412.zip";
var parts = reg.Split( filename, 4 );


回答5:

Obviously you are getting more parts because the last part of your file also contains "-".

An easy way to solve it is to join the remaining parts like this:

String lastpart = string.Join("-", names, 3, names.Length - 3);