/ / .Net: Ako skontrolovať nelegálne znaky v ceste? - .net, cesta, nelegálne znaky

.Net: Ako môžem skontrolovať nelegálne znaky v ceste? - .net, cesta, nelegálne znaky

Existuje spôsob, ako skontrolovať, či reťazec znamená precesta má neplatné znaky, v .Net? Viem, že by som mohol prechádzať cez každú postavu v Path.InvalidPathChars, aby som zistil, či môj String obsahoval jeden, ale ja by som radšej jednoduché, možno formálnejšie riešenie.

Je tu jeden?

Zistil som, že stále dostanem výnimku, ak budem kontrolovať len proti Get

aktualizácia:

Som "našiel GetInvalidPathChars nezahŕňakaždý znak neplatnej cesty. GetInvalidFileNameChars má ešte 5 ďalších, vrátane "?", Ktoré som narazil, a ja sa chystám prejsť na to a ja ohlásim, ak sa tiež ukáže ako neprimerané.

Aktualizácia 2:

GetInvalidFileNameChars určite nie je to, čo somchcieť. Obsahuje ":", ktoré bude obsahovať akékoľvek absolútne cesty ("C: čokoľvek"). Myslím, že budem musieť konečne použiť GetInvalidPathChars a pridať "?" A akékoľvek iné znaky, ktoré mi spôsobujú problémy pri príchode.

odpovede:

36 pre odpoveď č. 1

InvalidPathChars je zastaraný. Namiesto toho použite GetInvalidPathChars ()

    public static bool FilePathHasInvalidChars(string path)
{

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

Upraviť: Mierne dlhšie, ale zaobchádza s neplatnými znakmi cesta / súbor v jednej funkcii:

    // 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 pre odpoveď č. 2

Buďte opatrní, keď sa spoliehate na Path.GetInvalidFileNameChars, ktoré nemusia byť tak spoľahlivé, ako si myslíte. Všimnite si nasledujúcu poznámku v dokumentácii MSDN Path.GetInvalidFileNameChars:

Pole vrátené z tejto metódy je nie je zaručené, že obsahuje úplnú sadu znakov, ktoré sú neplatné v názvoch súborov a adresárov. Celá sada neplatných znakov sa môže líšiť podľasystém súborov. Napríklad na desktopových platformách so systémom Windows môžu znaky neplatných ciest obsahovať znaky ASCII / Unicode 1 až 31 a citovať ("), menšie ako (<), väčšie ako (>), potrubie (|), backspace ( b), nula (

Nie je to lepšie Path.GetInvalidPathChars metóda. Obsahuje presne rovnakú poznámku.


2 pre odpoveď č. 3

Je pravdepodobne príliš neskoro pre vás, ale môže pomôcť niekomu inému. Mala som rovnakú otázku a musel som nájsť spoľahlivý spôsob sanácie cesty.

Tu je to, čo som skončil s použitím, v troch krokoch:

Krok 1: Vlastné čistenie.

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

Krok 2: Skontrolujte všetky neplatné znaky, ktoré ešte neboli odstránené.

Jeden dodatočný verifikačný krok používam Path.GetInvalidPathChars() metódu zverejnenú vyššie na zistenie potenciálnych neplatných znakov, ktoré ešte neboli odstránené.

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

Krok 3: Vyčistite všetky špeciálne znaky zistené v kroku 2.

A nakoniec, používam túto metódu ako posledný krok na čistenie všetkého, čo zostalo. (od Ako odstrániť nelegálne znaky z cesty a názvov súborov?):

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

Pri prvom kroku zaznamenávam neplatný znak, ktorý nebol vyčistený. Rozhodla som sa ísť takým spôsobom, aby som zlepšil svoju vlastnú metódu, akonáhle sa zistí "únik". Nemôžem sa spoliehať na Path.GetInvalidFileNameChars() kvôli nasledujúcemu vyhláseniu a uvedené vyššie (z MSDN):

"Pole vrátené z tejto metódy nemôže obsahovať úplná sada znakov, ktoré sú neplatné v súbore a adresári Mená. "

Možno to nie je ideálne riešenie, ale vzhľadom na kontext mojej žiadosti a požadovanú úroveň spoľahlivosti je to najlepšie riešenie, ktoré som našiel.


1 pre odpoveď č. 4

Nakoniec som si vypožičal a skombinoval niekoľko interných implementácií .NET, aby som prišiel s výkonnou metódou:

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

Potom som ju použil ako tak, ale aj zabalil ho do skúšobného / úlovkového bloku pre bezpečnosť:

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

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

...
}

0 pre odpoveď č. 5

Aj ja som príliš neskoro, ale ak je úlohou overiť, či používateľ zadal niečo platné ako cestu, existuje kombinované riešenie pre cesty.

Path.GetInvalidFileNameChars() vracia zoznam znakov nelegálnych pre súbor, ale adresár sa riadi pravidlami súboru okrem separátorov (ktoré by sme mohli získať zo systému) a koreňový špecifikátor (C:, môžeme ju len odstrániť z vyhľadávania). Áno, Path.GetInvalidFileNameChars() nevracia kompletnú sadu, ale je lepšie, ako sa pokúsiť nájsť všetky z nich ručne.

takže:

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

Zistil som, že metódy ako Path.GetFileName nebudú naraziť na cesty ako C:* (čo je úplne neplatné) a dokonca kontrola založená na výnimkách nestačí. Jediná vec, ktorá narazí Path.GetPathRoot je neplatný root (napr CC:someDir). Všetko ostatné by sa malo robiť ručne.