4
\$\begingroup\$

Often I need to clean a file name using Path.GetInvalidFileNameChars(), however I do not know of a way to search for any of the invalid letters (except by using Regex) in one pass.

public string LoopMethod()
{
    StringBuilder sb = new StringBuilder(fileName);
    foreach(var invalidChar in Path.GetInvalidFileNameChars())
    {
        sb.Replace(invalidChar, '_');
    }
    return sb.ToString();
}


Regex invalidCharsRegex;
public void RegexMethodInit()
{
    var invalidChars = Path.GetInvalidPathChars().Select(c => Regex.Escape(c.ToString())).ToString();
    invalidCharsRegex = new Regex(string.Join("|", invalidChars));
}

public string RegexMethod(string fileName)
{
    return invalidCharsRegex.Replace(fileName, "_");
}

Is one of those ways the "correct" way to to this or is there a better function I am missing?

\$\endgroup\$
2
  • \$\begingroup\$ Related: forums.asp.net/t/1185961.aspx/1 \$\endgroup\$ Feb 21, 2013 at 23:28
  • \$\begingroup\$ @Leonid Path.GetInvalidPathChars() returns a char[] of characters that are illegal in a file name. What I wanted to know is what is the proper way to clean a filename from the returned char[], is it to just loop like in my example, or is there a function that can take in a char[] and replace on a string in one operation? \$\endgroup\$ Feb 22, 2013 at 0:11

2 Answers 2

4
\$\begingroup\$
foreach(var c in Path.GetInvalidPathChars())
    path = path.replace(c, '_')

That's a bit inefficient as it can allocate a string on every itteration, but usually not a problem. Alternative:

var chars = Path.GetInvalidPathChars()
path = new string(path.Select(c => chars.Contains(c) ? '_' : c).ToArray())
\$\endgroup\$
2
  • \$\begingroup\$ Ah, your answer is better, except that you are not using a set. Using a set may speed things up or slow them down depending on the size of the array. Either way this function should run fast. \$\endgroup\$
    – Leonid
    Feb 23, 2013 at 0:15
  • 3
    \$\begingroup\$ Come to think of it, this code is doing File IO, any of these solutions is fine. They'll all be several levels of magnitude faster than doing File IO. \$\endgroup\$ Feb 23, 2013 at 10:50
2
\$\begingroup\$

You can just make a regex of the "[abcdef]" type; it'll match all characters inside the brackets. No need to join them with |.

I use this function, which uses the above regex type, and utilizes the fact you can simply make a string from a character array. Since it was written for converting a document title to a file name it uses spaces as replace characters, and somewhat trims the final result by collapsing any double spaces.

public static String MakeSafeFileName(String input)
{
    // make regex of illegal characters list
    String illegalChars = "["+ Regex.Escape(new String(Path.GetInvalidFileNameChars())) + "]";
    // replace characters by space
    input = Regex.Replace(input, illegalChars, " ");
    // replace double spaces by a single space
    input = Regex.Replace(input, "\\s\\s+", " ");
    return input;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.