2009-06-18 15 views
11

Vedere l'oggetto di presentazione per la domanda.Controllo del nome file valido. Qual è il modo migliore?

1) Mi ricordo di aver visto una scelta davvero cool in VB.NET utilizzando LINQ per abbinare con "LIKE%'

2) So che le espressioni regolari lavoreranno e ho il sospetto che si tradurrà nel codice più breve e, probabilmente, non sarà troppo difficile da leggere per un semplice test come

Ecco quello che ho fatto Attenzione:... stai andando odi

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 

risposta

12

Vecchio ora, ma ho visto questo e solo dovuto aggiungere una nuova risposta. Le attuali risposte accettate e altre sono solo più complicate del necessario. In effetti, può essere ridotto a una sola riga:

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 

Anche se io non lo consiglio a scrivere in questo modo. Break it up solo un po 'per migliorare la leggibilità:

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 

Un altro punto qui, è che spesso il modo migliore per affrontare i problemi del file system è quello di lasciare che il file system vi dico: basta provare a aprire o creare il file in questione e gestire l'eccezione. Funziona particolarmente bene, perché probabilmente dovrai farlo comunque. Qualsiasi cosa tu faccia qui è uno sforzo duplicato per il lavoro che dovrai ancora inserire in un gestore di eccezioni.

+0

Mai troppo tardi per migliorare. Grazie. – ChadD

+2

Se possibile, lo scopo di questa funzione è di verificare i caratteri validi nel nome file. Ma se contiene caratteri non validi, si bloccherà sulla prima riga: Path.GetFileName (fileName) – David

+0

* "Non è garantito che la matrice restituita da questo metodo contenga il set completo di caratteri non validi nei nomi di file e directory. il set completo di caratteri non validi può variare a seconda del file system. Ad esempio, su piattaforme desktop basate su Windows, i caratteri di percorso non validi potrebbero includere caratteri ASCII/Unicode da 1 a 31, oltre a virgolette ("), minori di (<), maggiori di (>), pipe (|), backspace (\ b), null (\ 0) e tab (\ t). "* https://msdn.microsoft.com/en-us/library/system.io.path .getinvalidfilenamechars (v = vs.110) .aspx – mbomb007

0

Francamente, mi basta usare l'oggetto FileInfo built in. NET e controlla l'eccezione per l'invalidità. Vedere this riferimenti per i dettagli.

+0

Il codice potrebbe essere cercando di convalidare un percorso che non ha accesso a però. – patjbs

+0

Esattamente. Come nel mio caso. – ChadD

+3

Utilizzare le eccezioni per gestire il flusso di controllo è una cattiva pratica! –

2

Si tratta di una regex e C#, ma:

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

Questo SO è indipendente? Sarei cauto solo se l'app verrà mai eseguita sotto Mono. –

+1

+1 per essere una soluzione a due linee, -1 per essere compatibile solo in inglese ... :) –

10

Come su Path.GetInvalidFileNameChars e 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 
+0

Una risposta a sorpresa! Molto bene! – ChadD

+0

come può funzionare? Perché se il nome del file contiene già caratteri non validi, il tentativo di ottenere il nome file (riga 1) fa eccezione, perché GetFilename chiama CheckInvalidPathChars e pertanto genera l'eccezione –

+1

So che questa è una vecchia domanda ma il commento di Paul Farry sopra mi ha fatto dubitare della soluzione data, quindi mi piacerebbe correggerla nel caso in cui qualcun altro abbia gli stessi dubbi. Se si guarda la definizione di CheckInvalidPathChars, in realtà cerca solo 5 possibili caratteri non validi mentre GetInvalidFileNameChars() restituisce un elenco significativamente più lungo di caratteri non validi. Quindi il metodo di cui sopra sta sicuramente andando a prendere tutti i problemi, facendo affidamento su Path.GetFilename per chiamare CheckInvalidPathChars no. –

1

Anche se questo è abbastanza vecchio, è ancora valido, e sono finito qui cercando la soluzione a come controllare il nome del file per i caratteri non validi. Ho guardato la risposta accettata e ho trovato alcuni buchi.

Speriamo che queste modifiche siano di qualche utilità per qualcun altro.

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 
1

provare questo

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 
+1

Non si dovrebbe mai pianificare di utilizzare le eccezioni come parte del normale funzionamento dell'applicazione - Quando viene passato un nome file non valido, ciò causerebbe il CLR a generare una traccia completa dello stack (tra l'altro) [che è costoso] (http: // stackoverflow.com/a/4648011/156755). – Basic

+0

La cattiva pratica o la spesa computazionale non ha mai fermato Microsoft! – gls123

+0

Anche se non scriverei questa funzione in questo modo, direi che questo è il modo migliore per gestire il problema: basta creare il file già e gestire l'eccezione se hai un problema ... dopo tutto, è necessario scrivere comunque il gestore delle eccezioni a causa della natura volatile del file system. –

0

Ok. Buone idee. Ma l'iterazione manuale dei caratteri "non validi" non è il modo migliore, quando si lavora con migliaia di file.

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 
0

Prova questa

Funzione IsValidFileNameOrPath (nome ByVal come stringa) come booleano

Dim i come numero intero Dim dn, fn come stringa

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 
1

Sulla base di Joel Coehoorns soluzione ben scritto, Ho aggiunto alcune funzionalità aggiuntive per la convalida.

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

Non posso prendermi il merito di questo (ben due) transatlantico. L'ho trovato mentre cercavo su google, non ricordo dove l'ho trovato.

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

Essere più descrittivi postare qualsiasi risposta – Satendra

Problemi correlati