Оценка 840
[+0/-5]
Оценить ![]() ![]() ![]() ![]() ![]() ![]()
|
Библиотечная функция access позволяет определять режим доступа к файлу, а если второй параметр mode равен нулю, то определяется только существование файла.
#include <io.h>
bool FileExists(const char *fname)
{
returnaccess(fname, 0) != -1;
}
|
Хотя эта функция и не входит в стандарт C/C++, тем не менее, она присутствует в компиляторах Visual C++, Borland C++, Watcom C++ и многих других в неизменном виде.
Функция _findfirst возвращает информацию о первом файле, удовлетворяющем заданной маске поиска. Если указать точное имя файла, то мы сможем ответить на наш вопрос.
#include <io.h>
bool FileExists (const char *fname)
{
_finddata_t data;
long nFind = _findfirst(fname,&data);
if (nFind != -1)
{
// Если этого не сделать, то произойдет утечка ресурсов
_findclose(nFind);
return true;
}
return false;
}
|
С помощью этого способа можно определять не только существование отдельного файла, но также и группы файлов, соответствующей заданной маске. А если задать маску как "*.*", то можно узнать есть ли файлы в заданной директории.
Функция GetFileAttributes Win32 API возвращает атрибуты для заданного файла или каталога. В случае ошибки возвращается значение 0xFFFFFFFF.
#include <windows.h>
bool FileExists(LPCTSTR fname)
{
return::GetFileAttributes(fname) != DWORD(-1);
}
|
Этот способ используется во многих примерах из MSDN, что позволяет предположить, что это штатный способ для решения нашей задачи в Win API. Кроме того, это самый быстрый из приведенных здесь способов.
Этот способ аналогичен способу 2 с той лишь разницей, что для достижения результата используется функция Win32 API.
#include <windows.h>
bool FileExists(LPCTSTR fname)
{
WIN32_FIND_DATA wfd;
HANDLE hFind = ::FindFirstFile(fname, &wfd);
if (INVALID_HANDLE_VALUE != hFind)
{
// Если этого не сделать то произойдет утечка ресурсов
::FindClose(hFind);
return true;
}
return false;
}
|
MFC содержит класс-обёртку для функций Find... API. Мы вполне можем использовать этот класс.
#include <afx.h>
bool FileExists(LPCTSTR fname)
{
returnCFileFind().FindFile(fname) == TRUE;
}
|
Среди прочих классов, подобных MFC, WTL также содержит и CFindFile .Следовательно, этот способ внешне ни чем не отличается от предыдущего, кроме того, что не требует MFC.DLL. На самом деле этот способ намного быстрее предыдущего. Дело в том, что все функции класса CFindFile являются inline,так что код, генерируемый компилятором, почти целиком совпадает с кодом для способа 4.
#define _WTL_NO_CSTRING // только для любителей "чистого" API#include <AtlMisc.h>
bool FileExists(LPCTSTR fname)
{
returnCFindFile().FindFile(fname) == TRUE;
}
|
Ещё один способ из предложенных Александром Шаргиным - использование SHLWAPI Path API .
#include <windows.h>
#include <shlwapi.h>
#pragma comment(lib, "shlwapi")
bool FileExists(LPCTSTR fname)
{
return::PathFileExists(fname) == TRUE;
}
|
Правда у этого способа имеются определённые недостатки, которые значительно сужают его практическое применение:
Самый очевидный и самый громоздкий способ.
#include<windows.h>
bool FileExists(LPCTSTR fname)
{
HANDLE hFile = ::CreateFile(
fname, // file (or device) name0, // query access only
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, // share mode
NULL, // security attributes
OPEN_EXISTING, // disposition
FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN, // flags & attributes
NULL // template file
);
if (INVALID_HANDLE_VALUE != hFile)
{
::CloseHandle(hFile);
return true;
}
return false;
}
|
Данный метод состоит в создании временного объекта класса ifstream .Если файл с указанным именем не существует то operator void*() этого класса возвращает NULL pointer - иначе возвращается указатель на сам созданный объект (this). Это значение проверяется на NULL pointer - и ... все.
#include <fstream>
bool FileExists(const char *fname)
{
returnstd::ifstream(fname) != NULL;
}
|
... вернее почти все =)
В данном коде ifstream это typedef basic_ifstream < char, char_traits <char>> ifstream; если же Вы пользуетесь старыми заголовочными файлами (с расширением .h) - то для Вас ifstream - это никакой неtypedef- а самый настоящий класс. И все было бы прекрасно - если бы не одно но - в этом случае конструктор с именем файла в качестве параметра СОЗДАСТ файл (если он не существует) и в любом случае, проверка на существование файла даст положительный результат. Дело в том, что для "старого" ifstream 'а надо явно указывать что НЕ надо создавать файл через добавление флага ios::nocreate во втором параметре конструктора. А вот и сам код для такого случая:
#include <fstream.h>
bool FileExists(const char *fname)
{
return ::ifstream(fname, ios::in | ios::nocreate) != NULL;
}
|
Данный метод хорош тем что он 100% портабелен - то есть используются только возможности самого языка С++ (в лице его стандартной библиотеки - которая является его частью).
Могу вас обрадовать, в .NET все наши мучения закончатся. Для выяснения существования файла можно будет просто вызвать метод FileExists класса File . Например:
System.IO.File.FileExists("c:\\autoexec.bat"); |
Ни один из перечисленных способов не будет работать из .html документа. Зато из скрипта доступен Scripting.FileSystemObject и нам этого достаточно.
function FileExists(fname)
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
returnfso.FileExists (fname);
}
|
Мы вполне можем использовать Scripting.FileSystemObject и в COM-модуле:
HRESULT FileExists(LPOLESTR oszFilename)
{
CComPtr<IFileSystem> pfs;
HRESULT hr = pfs.CoCreateInstance(OLESTR("Scripting.FileSystemObject"));
if (SUCCEEDED(hr))
{
VARIANT_BOOL ret = VARIANT_FALSE;
hr = pfs->raw_FileExists(fname, &ret);
if (SUCCEEDED(hr))
hr = ret ? S_OK : S_FALSE;
}
return hr;
}
|
Фактически, это очень извращенный способ вызова все той же функции access() из способа 1, с той разницей, что FileSystemObject работает с именами файлов в UNICODE и под WindowsNT/2k передает имя файла напрямую, а под Windows 9x/Me (и даже 3.1 с интернет эксплорером!) сам преобразовывает его в ANSI.
Оценка 840
[+0/-5]
Оценить ![]() ![]() ![]() ![]() ![]() ![]()
|