I'm working in xmldataprovider and we have configuration value "source" this value may be local file or url like
c:开发者_如何学Python\data\test.xml --absolute data\test.xml --relative
or url http:\mysite\test.xml
how I can determine all this cases in code I'm working c#
private static bool IsLocalPath(string p)
{
return new Uri(p).IsFile;
}
...or, if you want to include support for certain invalid URIs...
private static bool IsLocalPath(string p)
{
if (p.StartsWith("http:\\"))
{
return false;
}
return new Uri(p).IsFile;
}
Example Usage
static void Main(string[] args)
{
CheckIfIsLocalPath("C:\\foo.txt");
CheckIfIsLocalPath("C:\\");
CheckIfIsLocalPath("http://www.txt.com");
}
private static void CheckIfIsLocalPath(string p)
{
var result = IsLocalPath(p); ;
Console.WriteLine("{0} {1} {2}", result, p, new Uri(p).AbsolutePath);
}
Just using new Uri(yourPath)
won't work in all cases.
Comparing various scenarios (via LinqPad).
var tests = new[] {
Path.GetTempFileName(),
Path.GetDirectoryName(Path.GetTempFileName()),
"http://in.ter.net",
"http://in.ter.net/",
"http://in.ter.net/subfolder/",
"http://in.ter.net/subfolder/filenoext",
"http://in.ter.net/subfolder/file.ext",
"http://in.ter.net/subfolder/file.ext?somequerystring=yes",
Path.GetFileName(Path.GetTempFileName()),
Path.Combine("subfolder", Path.GetFileName(Path.GetTempFileName())),
};
tests.Select(test => {
Uri u;
try {
u = new Uri(test);
} catch(Exception ex) {
return new {
test,
IsAbsoluteUri = false,
// just assume
IsFile = true,
};
}
return new {
test,
u.IsAbsoluteUri,
u.IsFile,
};
}).Dump();
Results
In case of a malformed path (non-existing path,empty string, null string) Uri(p).IsFile throws an exception. In my opinion is better to use two methods to discern what is what:
private bool PathIsLocalFile(string path)
{
return File.Exists(path);
}
private bool PathIsUrl(string path)
{
if (File.Exists(path))
return false;
try
{
Uri uri = new Uri(path);
return true;
}
catch (Exception)
{
return false;
}
}
//
Microsoft docs:
public static bool Exists(string path);
Returns: true if the caller has the required permissions and path contains the name of an existing file; otherwise, false. This method also returns false if path is null, an invalid path, or a zero-length string. If the caller does not have sufficient permissions to read the specified file, no exception is thrown and the method returns false regardless of the existence of path. //
Microsoft docs:
public Uri(string uriString);
Exceptions:
T:System.ArgumentNullException:
uriString is null.
T:System.UriFormatException:
uriString is empty.-or- The scheme specified in uriString is not correctly formed. See System.Uri.CheckSchemeName(System.String).-or- uriString contains too many slashes.-or- The password specified in uriString is not valid.-or- The host name specified in uriString is not valid.-or- The file name specified in uriString is not valid. -or- The user name specified in uriString is not valid.-or- The host or authority name specified in uriString cannot be terminated by backslashes.-or- The port number specified in uriString is not valid or cannot be parsed.-or- The length of uriString exceeds 65519 characters.-or- The length of the scheme specified in uriString exceeds 1023 characters.-or- There is an invalid character sequence in uriString.-or- The MS-DOS path specified in uriString must start with c:\.
Simply set the rule for all remote file, it should (and it must) include the protocol in the URI:
http://
ftp://
and for local file, it can be
file://
for absolute path and no protocol for relative.
Then simple regex could help extracting the right information.
This is a version of @drzaus 's answer avoiding exception handling approach. There is a Uri.TryCreate available.
var tests = new[] {
Path.GetTempFileName(),
Path.GetDirectoryName(Path.GetTempFileName()),
"http://in.ter.net",
"http://in.ter.net/",
"http://in.ter.net/subfolder/",
"http://in.ter.net/subfolder/filenoext",
"http://in.ter.net/subfolder/file.ext",
"http://in.ter.net/subfolder/file.ext?somequerystring=yes",
Path.GetFileName(Path.GetTempFileName()),
Path.Combine("subfolder", Path.GetFileName(Path.GetTempFileName()))};
tests.Select(test =>
{
if (Uri.TryCreate(test, UriKind.Absolute, out var u))
{
return new { test, u.IsAbsoluteUri, u.IsFile };
}
return new { test, IsAbsoluteUri = false, IsFile = true };
}
).Dump();
And as extension methods:
public static bool IsLocalAbsolutePath(this string input)
{
if (Uri.TryCreate(input, UriKind.Absolute, out var uri))
{
return uri.IsFile;
}
return false;
}
public static bool IsRemoteAbsolutePath(this string input)
{
if (Uri.TryCreate(input, UriKind.Absolute, out var uri))
{
return !uri.IsFile;
}
return false;
}
For anyone who would like to always get an absolute Uri:
bool TryGetAbsoluteUri(string? path, out Uri? uri)
{
if (string.IsNullOrWhiteSpace(path))
{
uri = null;
return false;
}
if (Uri.TryCreate(path, UriKind.Absolute, out uri))
return true;
return Uri.TryCreate(path, UriKind.Relative, out uri) &&
Uri.TryCreate(new Uri(Directory.GetCurrentDirectory(), UriKind.Absolute), uri, out uri);
}
This works with the above test cases, but converts any relative file's to their absolute Uri based on the current working directory.
Note what it doesn't do is check for invalid file characters, which is something you could add relatively easily using Path
.
精彩评论