Проверьте, является ли вход пути URL-адресом или локальным файлом

Я работаю в xmldataprovider, и у нас есть значение конфигурации "source", это значение может быть локальным файлом или URL-адресом как

c:\data\test.xml --absolute data\test.xml - относительный

или url http:\mysite\test.xml

как я могу определить все эти случаи в коде Я работаю С#

Ответы

Ответ 1

private static bool IsLocalPath(string p)
{
  return new Uri(p).IsFile;
}

... или, если вы хотите включить поддержку определенных недопустимых URI...

private static bool IsLocalPath(string p)
{
  if (p.StartsWith("http:\\"))
  {
    return false;
  }

  return new Uri(p).IsFile;
}

Пример использования

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

Ответ 2

Просто использование new Uri(yourPath) не будет работать во всех случаях.

Сравнение различных сценариев (через 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();

Результаты

Результаты проверки пути Linqpad

Ответ 3

Просто установите правило для всего удаленного файла, он должен (и должен) включить протокол в URI:

http://
ftp://

и для локального файла это может быть

file://

для абсолютного пути и протокола для относительного.

Тогда простое регулярное выражение может помочь извлечь правильную информацию.

Ответ 4

В случае некорректного пути (несуществующий путь, пустая строка, пустая строка) Uri (p).IsFile выдает исключение. На мой взгляд, лучше использовать два метода, чтобы различить, что есть:

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

Возвращает: true, если вызывающий объект имеет необходимые разрешения, а путь содержит имя существующего файла; в противном случае - false. Этот метод также возвращает false, если путь равен null, недопустимый путь или строка нулевой длины. Если вызывающий объект не имеет достаточных разрешений для чтения указанного файла, исключение не генерируется, и метод возвращает false независимо от наличия пути. //

Microsoft docs: 
public Uri(string uriString);

Исключения:

T:System.ArgumentNullException:

uriString имеет значение null.

T:System.UriFormatException:

uriString пуст.-or- Схема, указанная в uriString, неверно сформирована. См. System.Uri.CheckSchemeName(System.String).- or- uriString содержит слишком много slashes.-or- Пароль, указанный в uriString, недействителен. -или- Имя хоста, указанное в uriString, недействительно. -или- имя файла, указанное в uriString, недопустимо. -или- Имя пользователя, указанное в uriString, недействительно. -или- Имя хоста или органа, указанное в uriString, не может быть завершено обратными слэшами. -или- Номер порта, указанный в uriString, недействителен или не может быть разобран. -или- Длина uriString превышает 65519 символов.-Or- Длина схемы, указанной в uriString, превышает 1023 символов. -или- В uriString имеется некорректная последовательность символов.-Or- Путь MS-DOS, указанный в uriString, должен начинаться с c:.\

Ответ 5

Это версия ответа @drzaus, избегающая подхода к обработке исключений. Существует Uri.TryCreate.

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

И как методы расширения:

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