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

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

1) Я вспоминаю, что в VB.NET используется действительно классная опция, использующая LINQ для сопоставления с использованием "LIKE%"

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

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

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

Ответ 1

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

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

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

Ответ 2

Как насчет 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

Ответ 3

Это регулярное выражение и С#, но:

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

Ответ 4

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

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

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

Ответ 5

попробуйте это

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

Ответ 6

Основываясь на хорошо написанном решении Joel Coehoorns, я добавил некоторые дополнительные функции для проверки.

    ''' <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

Ответ 7

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

Ответ 8

Ok. Хорошие идеи. Но ручная итерация "недействительных" символов не является лучшим способом, когда вы работаете с тысячами файлов.

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

Ответ 9

Попробуйте это

Функция IsValidFileNameOrPath (ByVal name As String) В качестве логического

Dim я As Integer       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

Ответ 10

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

    Dim newFileName As String = "*Not<A>Good:Name|For/\File?"
    newFileName = String.Join("-", fileName.Split(IO.Path.GetInvalidFileNameChars))

Ответ 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