Допустимая проверка имени файла. Какой самый лучший способ?

Смотрите тему постановки вопроса.

1) Я помню, что видел очень интересный вариант в VB.NET, использующий LINQ для сопоставления, используя & quot; LIKE% & apos;

2) Я знаю, что регулярные выражения будут работать, и я подозреваю, что это приведет к самому короткому коду и, вероятно, не будет слишком сложным для чтения для такого простого теста.

Вот что я сделал. Предупреждение: ты будешь ненавидеть это.

<code>Private Shared Function FileNameIsOk(ByVal fileName As String) As Boolean

    For Position As Integer = 0 To fileName.Length - 1

        Dim Character As String = fileName.Substring(Position, 1).ToUpper
        Dim AsciiCharacter As Integer = Asc(Character)

        Select Case True

            Case Character = "_" 'allow _
            Case Character = "." 'allow .
            Case AsciiCharacter >= Asc("A") And AsciiCharacter <= Asc("A") 'Allow alphas
            Case AsciiCharacter >= Asc("0") AndAlso AsciiCharacter <= Asc("9") 'allow digits

            Case Else 'otherwise, invalid character
                Return False

        End Select

    Next

    Return True

End Function
</code>

Ответы на вопрос(11)

Public Function IsValidFileName(nFile As String) As Boolean
    Try
        Dim S As String = Path.GetFileName(nFile)
    Catch
        Return False
    End Try
    Return True
End Function
 14 дек. 2017 г., 12:46
Будьте более информативным при публикации любого ответа

using System;
using System.Text.RegularExpressions;

/// <summary>
/// Gets whether the specified path is a valid absolute file path.
/// </summary>
/// <param name="path">Any path. OK if null or empty.</param>
static public bool IsValidPath( string path )
{
    Regex r = new Regex( @"^(([a-zA-Z]\:)|(\\))(\\{1}|((\\{1})[^\\]([^/:*?<>""|]*))+)$" );
    return r.IsMatch( path );
}
 22 июн. 2009 г., 15:46
Является ли эта ОС независимой? Я буду осторожен, если приложение будет запущено под Mono.
 01 дек. 2010 г., 15:47
+1 за решение в две строки, -1 за совместимость только с английским ... :)

что он довольно старый, он все еще действителен, и я остановился здесь на поиске решения, как проверить имя файла на наличие недопустимых символов. Я посмотрел на принятый ответ и нашел несколько дыр.

Надеемся, что эти модификации будут кому-то полезны.

Public Function FilenameIsOK(ByVal fileNameAndPath As String) As Boolean
    Dim fileName As String = String.Empty
    Dim theDirectory As String = fileNameAndPath

    Dim p As Char = Path.DirectorySeparatorChar

    Dim splitPath() As String
    splitPath = fileNameAndPath.Split(p)
    If splitPath.Length > 1 Then
        fileName = splitPath(splitPath.Length - 1)
        theDirectory = String.Join(p, splitPath, 0, splitPath.Length - 1)
    End If

    For Each c As Char In Path.GetInvalidFileNameChars()
  ,      If fileName.Contains(c) Then
            Return False
        End If
    Next

    For Each c As Char In Path.GetInvalidPathChars()
        If theDirectory.Contains(c) Then
            Return False
        End If
    Next
    Return True
End Function

Честно говоря, я просто использовал объект FileInfo, встроенный в .NET, и проверил исключение для недействительности. Увидетьэтот ссылка для деталей.

 18 июн. 2009 г., 20:11
Код может пытаться проверить путь, к которому у него нет доступа.
 19 июн. 2009 г., 15:27
Использование исключений для управления потоком управления - плохая практика!
 ChadD06 окт. 2014 г., 01:31
Используйте File.Exists или Directory.Exists
 ChadD18 июн. 2009 г., 20:17
Именно так. Как в моем случае.
 19 июн. 2009 г., 20:05
@BobKing: расскажите об этом в Microsoft; было бы здорово иметь метод validate () в их FileInfo, но они выбрали путь исключения.

Функция IsValidFileNameOrPath (имя ByVal как строка) как логическое значение

Дим я как целое         Dim dn, fn As String

    i = InStrRev(name, "\") : dn = Mid(name, 1, i) : fn = Mid(name, i + 1)
    MsgBox("directory = " & dn & " : file = " & fn)

    If name Is Nothing Or Trim(fn) = "" Then
        MsgBox("null filename" & fn)
        Return False
    Else
        For Each badchar As Char In Path.GetInvalidFileNameChars
            If InStr(fn, badchar) > 0 Then
                MsgBox("invalid filename" & fn)
                Return False
            End If
        Next
    End If

    If dn <> "" Then
        If InStr(dn, "\\") > 0 Then
            MsgBox("duplicate \ =  " & dn)
            Return False
        End If
        For Each badChar As Char In Path.GetInvalidPathChars
            If InStr(dn, badChar) > 0 Then
                MsgBox("invalid directory=  " & dn)
                Return False
            End If
        Next
        If Not System.IO.Directory.Exists(dn) Then
            Try
                Directory.CreateDirectory(dn)
                'Directory.Delete(dn)
            Catch
                MsgBox("invalid path =  " & dn)
                Return False
            End Try
        End If
    End If
    Return True
End Function

На основе хорошо написанного решения Джоэла Кохорна я добавил некоторые дополнительные функции для проверки.

    ''' <summary>
    ''' Check if fileName is OK
    ''' </summary>
    ''' <param name="fileName">FileName</param>
    ''' <param name="allowPathDefinition">(optional) set true to allow path definitions. If set to false only filenames are allowed</param>
    ''' <param name="firstCharIndex">(optional) return the index of first invalid character</param>
    ''' <returns>true if filename is valid</returns>
    ''' <remarks>
    ''' based on Joel Coehoorn answer in 
    ''' http://stackoverflow.com/questions/1014242/valid-filename-check-what-is-the-best-way
    ''' </remarks>
    Public Shared Function FilenameIsOK(ByVal fileName As String, _
                                        Optional ByVal allowPathDefinition As Boolean = False, _
                                        Optional ByRef firstCharIndex As Integer = Nothing) As Boolean

        Dim file As String = String.Empty
        Dim directory As String = String.Empty

        If allowPathDefinition Then
            file = Path.GetFileName(fileName)
            directory = Path.GetDirectoryName(fileName)
        Else
            file = fileName
        End If

        If Not IsNothing(firstCharIndex) Then
            Dim f As IEnumerable(Of Char)
            f = file.Intersect(Path.GetInvalidFileNameChars())
            If f.Any Then
                firstCharIndex = Len(directory) + file.IndexOf(f.First)
                Return False
            End If

            f = directory.Intersect(Path.GetInvalidPathChars())
            If f.Any Then
                firstCharIndex = directory.IndexOf(f.First)
                Return False
            Else
                Return True
            End If
        Else
            Return Not (file.Intersect(Path.GetInvalidFileNameChars()).Any() _
                        OrElse _
                        directory.Intersect(Path.GetInvalidPathChars()).Any())
        End If

    End Function

попробуй это

Public Function IsValidFileName(ByVal fn As String) As Boolean
    Try
        Dim fi As New IO.FileInfo(fn)
    Catch ex As Exception
        Return False
    End Try
    Return True
End Function
 02 авг. 2016 г., 19:13
Хотя я бы не написал эту функцию таким образом, я бы сказал, что это лучший способ в конечном итоге решить проблему: просто создайте файл и обработайте исключение, если у вас есть проблема ... все, у вас будет написать обработчик исключений в любом случае из-за изменчивой природы файловой системы.
 11 янв. 2013 г., 10:45
Плохая практика или вычислительные затраты никогда не останавливали Microsoft!
 07 янв. 2013 г., 11:06
Вы никогда не должны планировать использовать исключения как часть нормальной работы вашего приложения. Когда передается недопустимое имя файла, это приводит к тому, что CLR генерирует полную трассировку стека (среди прочего)which is expensive.
Решение Вопроса

Старый сейчас, но я видел это и просто должен был добавить новый ответ. Текущие принятые и другие ответы намного сложнее, чем нужно. Фактически, это может быть уменьшено до единственной строки:

Public Shared Function FilenameIsOK(ByVal fileName as String) as Boolean
    Return Not (Path.GetFileName(fileName).Intersect(Path.GetInvalidFileNameChars()).Any() OrElse Path.GetDirectoryName(fileName).Intersect(Path.GetInvalidPathChars()).Any()) 
End Function

Хотя я бы не рекомендовал писать так. Немного разбейте его, чтобы улучшить читаемость:

Public Shared Function FilenameIsOK(ByVal fileName as String) as Boolean
    Dim file As String = Path.GetFileName(fileName)
    Dim directory As String = Path.GetDirectoryName(fileName)

    Return Not (file.Intersect(Path.GetInvalidFileNameChars()).Any() _
                OrElse _ 
                directory.Intersect(Path.GetInvalidPathChars()).Any()) 
End Function

Еще один момент, который здесь возникает, заключается в том, что зачастую лучший способ справиться с проблемами файловой системы - позволить файловой системе сообщить вам: просто попробуйте открыть или создать рассматриваемый файл и устранить исключение. Это работает особенно хорошо,because you'll likely have to do this anyway, Все, что вы здесь делаете, является дублирующим усилием для работы, которую вам все равно придется поместить в обработчик исключений.

 15 нояб. 2017 г., 16:43
@ mbomb007 Отсюда и последний абзац.
 ChadD17 янв. 2014 г., 22:48
Никогда не поздно, чтобы улучшить. Благодарю.
 15 нояб. 2017 г., 17:20
@JoelCoehoorn Я просто подумал, что нашел его источник, тем более что это документация к показанной функции.
 16 сент. 2016 г., 16:36
Если возможно, цель этой функции - проверить допустимые символы в имени файла. Но если он содержит недопустимые символы, в первой строке произойдет сбой: Path.GetFileName (fileName)
 15 нояб. 2017 г., 16:39
"The array returned from this method is not guaranteed to contain the complete set of characters that are invalid in file and directory names. The full set of invalid characters can vary by file system. For example, on Windows-based desktop platforms, invalid path characters might include ASCII/Unicode characters 1 through 31, as well as quote ("), less than (<), greater than (>), pipe (|), backspace (\b), null (\0) and tab (\t)." msdn.microsoft.com/en-us/library/…

Но ручная итерация «неверно» chars не лучший способ, когда вы работаете с тысячами файлов.

Public BadChars() As Char = IO.Path.GetInvalidFileNameChars

For m = 0 To thousands_of_files - 1
    '..
    if currFile.Name.ToCharArray.Intersect(BadChars).Count > 1 Then
         ' the Name is invalid - what u gonna do? =)
    end if
    '..
    '..
Next

Path.GetInvalidFileNameChars а такжеPath.GetInvalidPathChars?

Public Shared Function FilenameIsOK(ByVal fileNameAndPath as String) as Boolean
    Dim fileName = Path.GetFileName(fileNameAndPath)
    Dim directory = Path.GetDirectoryName(fileNameAndPath)
    For each c in Path.GetInvalidFileNameChars()
        If fileName.Contains(c) Then
            Return False
        End If
    Next
    For each c in Path.GetInvalidPathChars()
        If directory.Contains(c) Then
            Return False
        End If
    Next
    Return True
End Function
 22 окт. 2013 г., 21:50
Не работает с файлами, имеющими кантонские символы в имени. Я, вероятно, должен начать новую тему с конкретного отдельного вопроса; надеялся, что это сработает.
 ChadD19 июн. 2009 г., 04:04
Сюрприз ответ! Отлично сработано!
 28 апр. 2011 г., 12:45
Я знаю, что это старый вопрос, но комментарий Пола Фарри, приведенный выше, заставил меня усомниться в предложенном решении, поэтому я хотел бы исправить его на тот случай, если у кого-то еще возникнут такие же сомнения. Если вы посмотрите на определение CheckInvalidPathChars, то оно действительно только ищет 5 возможных недопустимых символов, в то время как GetInvalidFileNameChars () возвращает значительно более длинный список недопустимых символов. Таким образом, описанный выше метод определенно будет перехватывать все проблемы, в то время как использование метода Path.GetFilename для вызова CheckInvalidPathChars - нет.
 13 сент. 2010 г., 04:18
как это может работать? Потому что, если в имени файла уже есть недопустимые символы, то попытка получить имя файла (строка 1) приведет к исключению, потому что GetFilename вызывает CheckInvalidPathChars и, следовательно, выдает исключение

Я не могу взять кредит на этот (ну два) лайнер. Я нашел это, пока гуглял, не могу вспомнить, где я его нашел.

    Dim newFileName As String = "*Not<A>Good:Name|For/\File?"
    newFileName = String.Join("-", fileName.Split(IO.Path.GetInvalidFileNameChars))
 10 апр. 2018 г., 00:44
просто и легко! Я получил это в функцию, которая возвращает фиксированное имя файла напрямую.

Ваш ответ на вопрос