Пути к файлам с символами, отличными от ascii, и FileInfo в C#

Я получаю строку, которая более или менее выглядит так:

"C:\\bláh\\bleh"

Я делаю с ним FileInfo, но когда я проверяю его существование, он возвращает false:

var file = new FileInfo(path);
file.Exists;

Если я вручную переименую путь к

"C:\\blah\\bleh"

во время отладки и убедитесь, что blah существует с bleh внутри него, тогда file.Exists начнет возвращать true. Поэтому я считаю, что проблема заключается в не-ascii-символе.

Фактическая строка создается моей программой. Одна часть исходит из AppDomain приложения, то есть той части, которая содержит «á», а другая часть каким-то образом исходит от пользователя. Обе части собираются вместе с помощью Path.Combine. Я подтвердил правильность полученной строки двумя способами: скопировав ее из ошибки, которую генерирует моя программа, которая включает путь, в проводник, файл отлично открывается. Глядя на эту строку в отладчике, она выглядит правильно экранированной, в которой \ записываются как \. Отладчик буквально печатает «á».

Как мне обработать строку, чтобы даже если она содержит не-ascii-символы, она оказалась допустимым путем?


person pupeno    schedule 19.08.2009    source источник
comment
Откуда берется строка; он закодирован в файл кода или предоставлен пользователем?   -  person Fredrik Mörk    schedule 19.08.2009
comment
Фредрик Мёрк, я только что добавил эту информацию к самому вопросу.   -  person pupeno    schedule 19.08.2009
comment
Это странно. Я создал файл с тем же путем и именем, и следующий код печатает "True": FileInfo fi = new FileInfo("C:\\bláh\\bleh"); Console.WriteLine(fi.Exists);   -  person Fredrik Mörk    schedule 19.08.2009
comment
Какой код 'á' сгенерирован вашим приложением? И какой код у этого символа, если взять его из пути (Найти все папки на C:\, найти эту конкретную папку и посмотреть в отладке какой код)?   -  person Kamarey    schedule 19.08.2009


Ответы (6)


Вот метод, который будет обрабатывать диакритические знаки в именах файлов. Успех метода File.Exists зависит от того, как ваша система хранит имя файла.

public bool FileExists(string sPath)
{
  //Checking for composed and decomposed is to handle diacritics in filenames.  
  var pathComposed = sPath.Normalize(NormalizationForm.FormC);
  if (File.Exists(pathComposed))    
      return true;

   //We really need to check both possibilities.
   var pathDecomposed = sPath.Normalize(NormalizationForm.FormD);
   if (File.Exists(pathDecomposed))     
      return true;

   return false;
}
person Rick M    schedule 20.09.2012

попробуй это

    string sourceFile = @"C:\bláh\bleh";
    if (File.Exists(sourceFile))
    {

         Console.WriteLine("file exist.");

    }
    else
    {
        Console.WriteLine("file does not exist.");

    }

Примечание. Метод Exists не следует использовать для проверки пути, этот метод просто проверяет, существует ли файл, указанный в пути. Передача недопустимого пути в Exists возвращает false.

Для проверки пути вы можете использовать Directory.Exists.

person RRUZ    schedule 19.08.2009
comment
Я не пытаюсь проверить путь, я хочу убедиться, что файл действительно существует. - person pupeno; 19.08.2009

Я только что вручную создал папку bláh, содержащую bleh-файл, и с ее помощью этот код печатает True, как и ожидалось:

using System;
using System.IO;

namespace ConsoleApplication72
{
    class Program
    {
        static void Main(string[] args)
        {
            string filename = "c:\\bláh\\bleh";

            FileInfo fi = new FileInfo(filename);

            Console.WriteLine(fi.Exists);

            Console.ReadLine();
        }
    }
}

Я бы предложил проверить источник вашей строки - в частности, хотя ваш представитель 3k говорит против того, что это проблема, помните, что выражение обратной косой черты как \\ является артефактом синтаксиса C #, и вы хотите убедиться, что ваша строка действительно содержит только один \с.

person AakashM    schedule 19.08.2009
comment
Строка берется откуда-то еще, и я просто добавляю к ней дополнительные элементы с помощью Path.Combine. Когда я печатаю строку, она выглядит как c:\bláh\bleh, которую я могу скопировать и вставить в текстовое поле пути к файлу проводника, и он откроет файл. И когда я смотрю на это в отладчике, я вижу c:\\blah\\bleh, поэтому я считаю, что строка на самом деле правильная. Позже я попробую сделать это в консольном приложении, как и вы, и посмотрю, что произойдет. - person pupeno; 19.08.2009

Ссылаясь на ответ @adatapost, список недопустимых символов имени файла (полученный из System.IO.Path.GetInvalidFileNameChars() на самом деле не содержит обычных символов с диакритическими знаками.

Похоже, вы действительно задаете вопрос: "Как удалить диакритические знаки из строки (или, в данном случае, из пути к файлу)?".

Или, может быть, вы не задаете этот вопрос и действительно хотите найти файл с именем:

c:\blòh\bleh

(или что-то подобное). В этом случае вам нужно попытаться открыть файл с таким же именем, а не не c:\bloh\bleh.

person Eric Smith    schedule 19.08.2009
comment
Я хочу работать с файлом c:\blah\bleh, а не c:\blah\bleh. Я попробовал свою программу с c:\blah\bleh просто чтобы убедиться, что проблема была в á. Если я каким-либо образом изменю путь, я в конечном итоге укажу на несуществующий файл, потому что путь правильный (я могу скопировать и вставить его в проводнике, и правильный файл откроется). - person pupeno; 19.08.2009

Похоже, что «bleh» в пути — это каталог, а не файл. Чтобы проверить, существует ли папка, используйте метод Directory.Exists.

person Kamarey    schedule 19.08.2009

Проблема заключалась в следующем: программе не хватило прав для доступа к этому файлу. Исправление разрешений решило проблему. Кажется, что когда я не экспериментировал, мне каким-то образом удалось воспроизвести проблему с правами доступа, возможно, вручную создав папку без символа, отличного от ascii, и скопировав другую.

О... так неловко.

person pupeno    schedule 20.08.2009