Проверка существования файла

Общие вопросы, не зависящие от языка реализации.

Модераторы: Duncon, Hawk, Romeo, Eugie

evgenrpo
Сообщения: 12
Зарегистрирован: 31 май 2009, 21:26
Контактная информация:

Работаю WINAPI C++.
я создаю файлы .тхт . подписеваю их по руски. Появляется проблема .Примеру создал файл Техт.тхт. второй создаю техт.тхт. Второй заменяет первый все данные теряются.
пытаюс проверить существующий из создаваемым.
английский без проблем , а вот руский проблема.

Код: Выделить всё

com=0;
lstrcpy(name2,pFileData.cFileName);
//name2 существующий файл
//name создаваем файл
wcsupr(name2);
wcsupr(name);
if(wcswcs(name2,name))
{
	con=1;
}
return con;
Как заставить руский техт перейти на верхний регистер?
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Нужно не сравнивать имена файлов, а спросить у ОС есть ли такой файл, таким образом полностью возложив ответственность по проверке регистра и дургих атрибутов на операционную систему.

Для проверки существования файла можно воспользоваться такой функцией:

Код: Выделить всё

bool IsFileExist(LPCTSTR strFileName)
{
   HANDLE hFile = ::CreateFile(strFileName,
                        GENERIC_READ,
                        FILE_SHARE_READ,
                        NULL, 
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);
   return (hFile != INVALID_HANDLE_VALUE)
}
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
evgenrpo
Сообщения: 12
Зарегистрирован: 31 май 2009, 21:26
Контактная информация:

Спасибо!!!
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

Romeo, Ага, а если файл при проверке открылся, то кто его закрывать будет (хэндл удалять)? Да и, плюс ко всему, это файловая операция, т.е. медленная (относительно, конечно).

Еще, если я правильно соображаю (и помню смысл всех мал-мала параметров CreateFile-а), твой способ не всегда даст верный результат. Например, если файл полность захвачен кем-то в эксклюзивном режиме, то CreateFile его и только на чтение не сможет открыть. И вернет результат, что нет такого файла.

Я проверял существование (в C++) через ф-ию access.
Она еще удобна тем (но не для данного случая это удобство не нужно), что можно проверить не только существование, но и режим доступа. Т.е., например, файл может существовать, а изменять его нельзя (нет доступа на запись).

Вот первая попавшаяся страница с описанием этой ф-ии:

Тогда проверка на существование файла будет выглядеть:

Код: Выделить всё

if (access (pathname,
                0)  // - 00 Проверка только на существование
    == 0)
{
 // Файл существует
}
else      
{
 // Файл НЕ существует
};
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

По поводу незакрытого хэндла полностью согласен. Я просто на скорую руку повыбрасывал часть функциональности готовой функции. Правильный код следующий:

Код: Выделить всё

bool IsFileExist(LPCTSTR strFileName)
{
   HANDLE hFile = ::CreateFile(strFileName,
                        GENERIC_READ,
                        FILE_SHARE_READ,
                        NULL,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);
   if (hFile != INVALID_HANDLE_VALUE)
   {
      ::CloseHandle(hFile);
      return true;
   }

   return false;
}
На счёт скорости готов спорить. Функция access разве не обращается к диску? :)

В целом соглашусь, что использование access более корректно именно для проверки существования. Я тоже пользовался этой функцией, просто сразу забыл о ней и привёл код, который был призван выполнять несколько другие задачи.

Кстати, ты забыл указать самый главный плюс функции access. Она входит в стандарт ANSI ISO 97, то есть код, который использует эту функцию по определению является кроссплатформенным.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Hawk
Сообщения: 216
Зарегистрирован: 17 фев 2004, 14:52
Откуда: СПб
Контактная информация:

Для проверки существования файла в виндах проще пользоваться функцией GetFileAttributes() она не открывает файл и проще в использовании. Типа -

Код: Выделить всё

bool IsFileExist(LPCTSTR strFileName)
{
      return GetFileAttributes(strFileName) != 0xFFFFFFFF;
}
Правда она и на папки будет срабатывать.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Чтобы на директориях не срабатывало, то можно подправить вот так:

Код: Выделить всё

bool IsFileExist(LPCTSTR strFileName)
{
   DWORD dwAttr = GetFileAttributes(strFileName);
   return (dwAttr != 0xFFFFFFFF) && (0 == (dwAttr & FILE_ATTRIBUTE_DIRECTORY));
}
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

Romeo писал(а):Функция access разве не обращается к диску? :)
Но она, как я понимаю, не открывает файл. Я не знаток тонкостей обращения к файлам, но, помнится, именно открытие/закрытие файлов - "медленные" функции.
Hawk писал(а):Правда она и на папки будет срабатывать.
access тоже, как я понимаю, работает с каталогами. Но в данном случае это не есть плохо. Т.к. здесь конечная цель создать файл с таким именем, и проверка идет потому, что человек опасается затереть уже существующий. Но если есть каталог с таким же именем, то файл создать также не удастся.
azrael
Сообщения: 89
Зарегистрирован: 31 май 2009, 15:30
Контактная информация:

Извините, можт я чего-то не понял, но скажите, зачем нужно изобретать велосипеды, если есть стандартная функция FileExists?
И зачем предлагать человеку всякие access'ы под предлогом кроссплатформенности, если он сказал, что пишет на WinAPI?
Не понимаю этой темы :) )
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

BBB, долгая операцию - это обращение к файловой системе. На фоне этой операции открытие файла пройдёт практически не заметно.

azrael, ты говоришь о функции ATLPath::FileExists? Если да, то эта функция не является "стандартной". Для её вызова нужно подключать библиотеку ATL, что не является правильным решением, если при подключении библиотеки будет вызвана всего одна функция из этой библиотеки и, более того, если существует полноценный аналог не использующий никаких других библиотек.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить