Очистка пути к файлу в C # без ущерба для буквы диска - PullRequest
0 голосов
/ 17 декабря 2018

Мне нужно обработать некоторые пути к файлам в C #, которые могут содержать недопустимые символы, например:

C:\path\something\output_at_13:26:43.txt

в этом пути, : s в отметке времени делают имя файла недействительным, и я хочузаменить их другим безопасным символом.

Я искал здесь решения для SO, но, похоже, все они основаны на чем-то вроде:

path = string.Join("_", path.Split(Path.GetInvalidFileNameChars()));

или похожих решениях.Эти решения, однако, не являются хорошими, потому что они портят букву диска, и я получаю вывод:

C_\path\something\output_at_13_26_43.txt

Я пытался использовать Path.GetInvalidPathChars(), но он все еще не работает, потому что он не работаетвключите : в недопустимые символы, чтобы он не заменял символы в имени файла.

Итак, выяснив это, я попытался сделать следующее:

string dir = Path.GetDirectoryName(path);
string file = Path.GetFileName(path);
file = string.Join(replacement, file.Split(Path.GetInvalidFileNameChars()));
dir = string.Join(replacement, dir.Split(Path.GetInvalidPathChars()));

path = Path.Combine(dir, file);

, ноэто тоже нехорошо, потому что : s в имени файла, кажется, мешают логике Path.GetFilename(), и он возвращает только последний фрагмент после последнего :, поэтому я теряю части пути.

Как мне сделать это "правильно" без хакерских решений?

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Вы определенно должны убедиться, что вы получаете только правильные имена файлов.

Если вы не можете и уверены, что ваши имена каталогов будут такими, вы можете разделить путь до последней обратной косой черты (при условии, что Windows) и собрать строку:

public static string SanitizePath(string path)
{
    var lastBackslash = path.LastIndexOf('\\');

    var dir = path.Substring(0, lastBackslash);
    var file = path.Substring(lastBackslash, path.Length - lastBackslash);

    foreach (var invalid in Path.GetInvalidFileNameChars())
    {
        file = file.Replace(invalid, '_');
    }

    return dir + file;
}
0 голосов
/ 17 декабря 2018

Вы можете написать простое дезинфицирующее средство, которое повторяет каждый символ и знает, когда ожидать двоеточие в качестве разделителя дисков.Этот будет поймать любую комбинацию буквы AZ, сопровождаемой непосредственно ":".Он также обнаружит разделители пути и не избежит их.Он не обнаружит пробелы в начале входной строки, поэтому в случае, если ваши входные данные могут прийти вместе с ними, вам придется сначала их обрезать или соответственно изменить дезинфицирующее средство:

enum ParserState {
    PossibleDriveLetter,
    PossibleDriveLetterSeparator,
    Path
}

static string SanitizeFileName(string input) {
    StringBuilder output = new StringBuilder(input.Length);
    ParserState state = ParserState.PossibleDriveLetter;
    foreach(char current in input) {
        if (((current >= 'a') && (current <= 'z')) || ((current >= 'A') && (current <= 'Z'))) {
            output.Append(current);
            if (state == ParserState.PossibleDriveLetter) {
                state = ParserState.PossibleDriveLetterSeparator;
            }
            else {
                state = ParserState.Path;
            }
        }
        else if ((current == Path.DirectorySeparatorChar) ||
            (current == Path.AltDirectorySeparatorChar) ||
            ((current == ':') && (state == ParserState.PossibleDriveLetterSeparator)) ||
            !Path.GetInvalidFileNameChars().Contains(current)) {

            output.Append(current);
            state = ParserState.Path;
        }
        else {
            output.Append('_');
            state = ParserState.Path;
        }
    }
    return output.ToString();
}

Вы можете попробуйте здесь .

...