/ / .Net: como faço para verificar caracteres ilegais em um caminho? - .net, caminho, caracteres ilegais

.Net: Como faço para verificar caracteres ilegais em um caminho? - .net, caminho, caracteres ilegais

Existe uma maneira de verificar se uma String significavacaminho tem caracteres inválidos, em .net? Eu sei que eu poderia fazer uma iteração sobre cada caractere em Path.InvalidPathChars para ver se minha String continha uma, mas eu preferia uma solução simples, talvez mais formal.

Existe um?

Eu descobri que ainda obtenho uma exceção se apenas verificar contra Get

Atualizar:

Eu encontrei GetInvalidPathChars não cobrecada caractere de caminho inválido. GetInvalidFileNameChars tem mais 5, incluindo "?", Que eu encontrei. Eu vou mudar para isso, e eu vou informar se ele também se mostra inadequado.

Atualização 2:

GetInvalidFileNameChars definitivamente não é o que euquer. Ele contém ":", que qualquer caminho absoluto irá conter ("C: whatever"). Eu acho que eu vou ter que usar GetInvalidPathChars depois de tudo, e adicionar "?" E quaisquer outros caracteres que me causem problemas à medida que eles surgem. Melhores soluções são bem-vindas.

Respostas:

36 para resposta № 1

InvalidPathChars foi reprovado. Use GetInvalidPathChars () em vez disso:

    public static bool FilePathHasInvalidChars(string path)
{

return (!string.IsNullOrEmpty(path) && path.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0);
}

Editar: ligeiramente mais longo, mas trata o caminho vs caracteres de arquivo inválidos em uma função:

    // WARNING: Not tested
public static bool FilePathHasInvalidChars(string path)
{
bool ret = false;
if(!string.IsNullOrEmpty(path))
{
try
{
// Careful!
//    Path.GetDirectoryName("C:DirectorySubDirectory")
//    returns "C:Directory", which may not be what you want in
//    this case. You may need to explicitly add a trailing 
//    if path is a directory and not a file path. As written,
//    this function just assumes path is a file path.
string fileName = System.IO.Path.GetFileName(path);
string fileDirectory = System.IO.Path.GetDirectoryName(path);

// we don"t need to do anything else,
// if we got here without throwing an
// exception, then the path does not
// contain invalid characters
}
catch (ArgumentException)
{
// Path functions will throw this
// if path contains invalid chars
ret = true;
}
}
return ret;
}

4 para resposta № 2

Tenha cuidado ao confiar em Path.GetInvalidFileNameChars, que pode não ser tão confiável como você "d pensa. Observe a observação a seguir na documentação do MSDN sobre Path.GetInvalidFileNameChars:

A matriz retornada deste método é Não é garantido que contenha o conjunto completo de caracteres inválidos em nomes de arquivos e diretórios. O conjunto completo de caracteres inválidos pode variar de acordo comsistema de arquivo. Por exemplo, em plataformas de desktop baseadas em Windows, caracteres de caminho inválidos podem incluir caracteres ASCII / Unicode 1 a 31, bem como aspas ("), menor que (<), maior que (>), pipe (|), backspace ( b), nulo (

Não é melhor com Path.GetInvalidPathChars método. Ele contém exatamente o mesmo comentário.


2 para resposta № 3

Provavelmente é tarde demais para você, mas pode ajudar alguém. Eu enfrentei o mesmo problema e precisava encontrar uma maneira confiável de higienizar um caminho.

Aqui está o que acabei usando em 3 etapas:

Etapa 1: limpeza personalizada.

public static string RemoveSpecialCharactersUsingCustomMethod(this string expression, bool removeSpecialLettersHavingASign = true)
{
var newCharacterWithSpace = " ";
var newCharacter = "";

// Return carriage handling
// ASCII LINE-FEED character (LF),
expression = expression.Replace("n", newCharacterWithSpace);
// ASCII CARRIAGE-RETURN character (CR)
expression = expression.Replace("r", newCharacterWithSpace);

// less than : used to redirect input, allowed in Unix filenames, see Note 1
expression = expression.Replace(@"<", newCharacter);
// greater than : used to redirect output, allowed in Unix filenames, see Note 1
expression = expression.Replace(@">", newCharacter);
// colon: used to determine the mount point / drive on Windows;
// used to determine the virtual device or physical device such as a drive on AmigaOS, RT-11 and VMS;
// used as a pathname separator in classic Mac OS. Doubled after a name on VMS,
// indicates the DECnet nodename (equivalent to a NetBIOS (Windows networking) hostname preceded by "\".).
// Colon is also used in Windows to separate an alternative data stream from the main file.
expression = expression.Replace(@":", newCharacter);
// quote : used to mark beginning and end of filenames containing spaces in Windows, see Note 1
expression = expression.Replace(@"""", newCharacter);
// slash : used as a path name component separator in Unix-like, Windows, and Amiga systems.
// (The MS-DOS command.com shell would consume it as a switch character, but Windows itself always accepts it as a separator.[16][vague])
expression = expression.Replace(@"/", newCharacter);
// backslash : Also used as a path name component separator in MS-DOS, OS/2 and Windows (where there are few differences between slash and backslash); allowed in Unix filenames, see Note 1
expression = expression.Replace(@"", newCharacter);
// vertical bar or pipe : designates software pipelining in Unix and Windows; allowed in Unix filenames, see Note 1
expression = expression.Replace(@"|", newCharacter);
// question mark : used as a wildcard in Unix, Windows and AmigaOS; marks a single character. Allowed in Unix filenames, see Note 1
expression = expression.Replace(@"?", newCharacter);
expression = expression.Replace(@"!", newCharacter);
// asterisk or star : used as a wildcard in Unix, MS-DOS, RT-11, VMS and Windows. Marks any sequence of characters
// (Unix, Windows, later versions of MS-DOS) or any sequence of characters in either the basename or extension
// (thus "*.*" in early versions of MS-DOS means "all files". Allowed in Unix filenames, see note 1
expression = expression.Replace(@"*", newCharacter);
// percent : used as a wildcard in RT-11; marks a single character.
expression = expression.Replace(@"%", newCharacter);
// period or dot : allowed but the last occurrence will be interpreted to be the extension separator in VMS, MS-DOS and Windows.
// In other OSes, usually considered as part of the filename, and more than one period (full stop) may be allowed.
// In Unix, a leading period means the file or folder is normally hidden.
expression = expression.Replace(@".", newCharacter);
// space : allowed (apart MS-DOS) but the space is also used as a parameter separator in command line applications.
// This can be solved by quoting, but typing quotes around the name every time is inconvenient.
//expression = expression.Replace(@"%", " ");
expression = expression.Replace(@"  ", newCharacter);

if (removeSpecialLettersHavingASign)
{
// Because then issues to zip
// More at : http://www.thesauruslex.com/typo/eng/enghtml.htm
expression = expression.Replace(@"ê", "e");
expression = expression.Replace(@"ë", "e");
expression = expression.Replace(@"ï", "i");
expression = expression.Replace(@"œ", "oe");
}

return expression;
}

Etapa 2: verifique os caracteres inválidos que ainda não foram removidos.

Um passo de verificação extra, eu uso o Path.GetInvalidPathChars() método postado acima para detectar possíveis caracteres inválidos que ainda não foram removidos.

public static bool ContainsAnyInvalidCharacters(this string path)
{
return (!string.IsNullOrEmpty(path) && path.IndexOfAny(Path.GetInvalidPathChars()) >= 0);
}

Etapa 3: limpe os caracteres especiais detectados na etapa 2.

E finalmente, eu uso este método como passo final para limpar tudo o que resta. (por Como remover caracteres ilegais do caminho e nomes de arquivos?):

public static string RemoveSpecialCharactersUsingFrameworkMethod(this string path)
{
return Path.GetInvalidFileNameChars().Aggregate(path, (current, c) => current.Replace(c.ToString(), string.Empty));
}

Eu registro qualquer caractere inválido não limpo na primeira etapa. Eu escolho fazer isso para melhorar meu método personalizado assim que um "vazamento" é detectado. Eu não posso confiar na Path.GetInvalidFileNameChars() devido à seguinte declaração relatada acima (da MSDN):

"A matriz retornada deste método não tem garantia de conter o conjunto completo de caracteres inválidos no arquivo e no diretório nomes. "

Pode não ser a solução ideal, mas dado o contexto da minha aplicação e o nível de confiabilidade exigido, essa é a melhor solução que encontrei.


1 para resposta № 4

Acabei pegando emprestado e combinando algumas implementações internas do .NET para criar um método de desempenho:

/// <summary>Determines if the path contains invalid characters.</summary>
/// <remarks>This method is intended to prevent ArgumentException"s from being thrown when creating a new FileInfo on a file path with invalid characters.</remarks>
/// <param name="filePath">File path.</param>
/// <returns>True if file path contains invalid characters.</returns>
private static bool ContainsInvalidPathCharacters(string filePath)
{
for (var i = 0; i < filePath.Length; i++)
{
int c = filePath[i];

if (c == """ || c == "<" || c == ">" || c == "|" || c == "*" || c == "?" || c < 32)
return true;
}

return false;
}

Eu usei então como assim mas também embrulhei isto em um bloco de tentativa / captura para segurança:

if ( !string.IsNullOrWhiteSpace(path) && !ContainsInvalidPathCharacters(path))
{
FileInfo fileInfo = null;

try
{
fileInfo = new FileInfo(path);
}
catch (ArgumentException)
{
}

...
}

0 para a resposta № 5

Eu também estou muito atrasado. Mas se a tarefa é validar se o usuário inseriu algo válido como caminho, há uma solução combinada para caminhos.

Path.GetInvalidFileNameChars() retorna lista de caracteres ilegais para o arquivo, mas o diretório segue as regras do arquivo, exceto os separadores (que poderíamos obter do sistema) e o especificador raiz (C:, podemos apenas removê-lo da pesquisa). Sim, Path.GetInvalidFileNameChars() retorna não o conjunto completo, mas é melhor do que tentar encontrar todos eles manualmente.

Assim:

private static bool CheckInvalidPath(string targetDir)
{
string root;
try
{
root = Path.GetPathRoot(targetDir);
}
catch
{
// the path is definitely invalid if it has crashed
return false;
}

// of course it is better to cache it as it creates
// new array on each call
char[] chars = Path.GetInvalidFileNameChars();

// ignore root
for (int i = root.Length; i < targetDir.Length; i++)
{
char c = targetDir[i];

// separators are allowed
if (c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar)
continue;

// check for illegal chars
for (int j = 0; j < chars.Length; j++)
if (c == chars[j])
return false;
}

return true;
}

Eu descobri que métodos como Path.GetFileName não vai falhar por caminhos como C:* (o que é completamente inválido) e mesmo cheque baseado em exceção não é suficiente. A única coisa que vai bater o Path.GetPathRoot é raiz inválida (como CC:someDir). Então tudo o resto deve ser feito manualmente.