104

ファイル名として使用したい「Foo:Bar」のような文字列がありますが、Windowsでは「:」文字をファイル名に使用できません。

「Foo:Bar」を「Foo-Bar」のようなものに変える方法はありますか?

4

15 に答える 15

164

次のようなことを試してください:

string fileName = "something";
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
   fileName = fileName.Replace(c, '_');
}

編集:

GetInvalidFileNameChars()は 10 文字または 15 文字を返すため、単純な文字列ではなく a を使用することStringBuilderをお勧めします。元のバージョンは時間がかかり、より多くのメモリを消費します。

于 2009-03-06T22:09:40.430 に答える
36
fileName = fileName.Replace(":", "-") 

ただし、Windows で使用できない文字は ":" だけではありません。次のことも処理する必要があります。

/, \, :, *, ?, ", <, > and |

これらは System.IO.Path.GetInvalidFileNameChars(); に含まれています。

また (Windows の場合)、「.」ファイル名の唯一の文字にすることはできません (「.」、「..」、「...」などは無効です)。「.」を使用してファイルに名前を付けるときは注意してください。たとえば、次のようになります。

echo "test" > .test.

「.test」という名前のファイルを生成します

最後に、本当に正しく処理したい場合は、注意が必要な特別なファイル名がいくつかあります。Windows では、次の名前のファイルを作成できません。

CON, PRN, AUX, CLOCK$, NUL
COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9
LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
于 2009-03-06T22:14:28.953 に答える
15

これは効率的ではありませんが、もっと楽しいです:)

var fileName = "foo:bar";
var invalidChars = System.IO.Path.GetInvalidFileNameChars();
var cleanFileName = new string(fileName.Where(m => !invalidChars.Contains(m)).ToArray<char>());
于 2011-11-10T16:16:56.887 に答える
9

Linqwhich uses を使用した受け入れられた回答のバージョンは次のEnumerable.Aggregateとおりです。

string fileName = "something";

Path.GetInvalidFileNameChars()
    .Aggregate(fileName, (current, c) => current.Replace(c, '_'));
于 2015-12-10T17:48:55.593 に答える
7

ディエゴは正しい解決策を持っていますが、そこには非常に小さな間違いが 1 つあります。使用されている string.Replace のバージョンは string.Replace(char, char) である必要があります。string.Replace(char, string) はありません。

回答を編集できないか、マイナーな変更を加えただけです。

したがって、次のようになります。

string fileName = "something";
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
   fileName = fileName.Replace(c, '_');
}
于 2009-09-09T07:49:16.607 に答える
5

StringBuilder完全な効率のためにIndexOfAny一括追加を使用するバージョンを次に示します。また、重複した文字列を作成するのではなく、元の文字列を返します。

最後に大事なことを言い忘れましたが、好きなようにカスタマイズできるそっくりな文字を返す switch ステートメントがあります。Unicode.org の confusables lookupを調べて、フォントに応じてどのようなオプションがあるかを確認してください。

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();
}

...、または のような予約済みの名前はチェックされませんCON。これは、置き換えが明確でないためです。

于 2015-05-08T14:20:41.677 に答える
-2

sedこれは、次のコマンドで実行できます。

 sed -e "
 s/[?()\[\]=+<>:;©®”,*|]/_/g
 s/"$'\t'"/ /g
 s/–/-/g
 s/\"/_/g
 s/[[:cntrl:]]/_/g"
于 2010-12-11T01:00:52.837 に答える