Ahmed
Ahmed

Reputation: 361

Check if the path input is URL or Local File

I'm working in xmldataprovider and we have configuration value "source" this value may be local file or url like

c:\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#

Upvotes: 31

Views: 32772

Answers (6)

thargy
thargy

Reputation: 191

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.

Upvotes: 0

natenho
natenho

Reputation: 5591

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

Upvotes: 2

user9117077
user9117077

Reputation:

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:\.

Upvotes: 3

drzaus
drzaus

Reputation: 24994

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

Linqpad results of path checking

Upvotes: 3

MaxGuernseyIII
MaxGuernseyIII

Reputation:

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

Upvotes: 43

xandy
xandy

Reputation: 27411

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.

Upvotes: 1

Related Questions