How to make a valid Windows filename from an arbitrary string?

后端 未结 14 933
伪装坚强ぢ
伪装坚强ぢ 2020-12-23 02:50

I\'ve got a string like \"Foo: Bar\" that I want to use as a filename, but on Windows the \":\" char isn\'t allowed in a filename.

Is there a method that will turn \

相关标签:
14条回答
  • 2020-12-23 03:32

    Here's a version that uses StringBuilder and IndexOfAny with bulk append for full efficiency. It also returns the original string rather than create a duplicate string.

    Last but not least, it has a switch statement that returns look-alike characters which you can customize any way you wish. Check out Unicode.org's confusables lookup to see what options you might have, depending on the font.

    public static string GetSafeFilename(string arbitraryString)
    {
        var invalidChars = System.IO.Path.GetInvalidFileNameChars();
        var replaceIndex = arbitraryString.IndexOfAny(invalidChars, 0);
        if (replaceIndex == -1) return arbitraryString;
    
        var r = new StringBuilder();
        var i = 0;
    
        do
        {
            r.Append(arbitraryString, i, replaceIndex - i);
    
            switch (arbitraryString[replaceIndex])
            {
                case '"':
                    r.Append("''");
                    break;
                case '<':
                    r.Append('\u02c2'); // '˂' (modifier letter left arrowhead)
                    break;
                case '>':
                    r.Append('\u02c3'); // '˃' (modifier letter right arrowhead)
                    break;
                case '|':
                    r.Append('\u2223'); // '∣' (divides)
                    break;
                case ':':
                    r.Append('-');
                    break;
                case '*':
                    r.Append('\u2217'); // '∗' (asterisk operator)
                    break;
                case '\\':
                case '/':
                    r.Append('\u2044'); // '⁄' (fraction slash)
                    break;
                case '\0':
                case '\f':
                case '?':
                    break;
                case '\t':
                case '\n':
                case '\r':
                case '\v':
                    r.Append(' ');
                    break;
                default:
                    r.Append('_');
                    break;
            }
    
            i = replaceIndex + 1;
            replaceIndex = arbitraryString.IndexOfAny(invalidChars, i);
        } while (replaceIndex != -1);
    
        r.Append(arbitraryString, i, arbitraryString.Length - i);
    
        return r.ToString();
    }
    

    It doesn't check for ., .., or reserved names like CON because it isn't clear what the replacement should be.

    0 讨论(0)
  • 2020-12-23 03:33

    Another simple solution:

    private string MakeValidFileName(string original, char replacementChar = '_')
    {
      var invalidChars = new HashSet<char>(Path.GetInvalidFileNameChars());
      return new string(original.Select(c => invalidChars.Contains(c) ? replacementChar : c).ToArray());
    }
    
    0 讨论(0)
提交回复
热议问题