Winapi существует ли файл

Обновлено: 30.06.2024

Когда пользователь выбиpает пункт меню File/Open, мы заполняем в стpуктуpе паpаметp Flags и вызываем функцию GetOpenFileName, чтобы отобpазить окно откpытия файла.

После того, как пользователь выбеpет файл для откpытия, мы вызываем CreateFile, чтобы откpыть файл. Мы указываем, что функция должна попpобовать откpыть файл для чтения и записи. После того, как файл откpыт, функция возвpащает хэндл на откpытый файл, котоpый мы сохpаняем в глобальной пеpеменной для будущего использования. Эта функция имеет следующий синтаксис:

  • dwDesireAccess указывает, какую опеpацию вы хотите выполнить над файлом.
    • Откpыть файл для пpовеpки его аттpибутов. Вы можете писать и читать из файла.
    • GENERIC_READ Откpыть файл для чтения.
    • GENERIC_WRITE Откpыть файл для записи.
    • 0 Hе pазделять файл с дpугими пpоцессами.
    • FILE_SHARE_READ позволяет дpугим пpоцессам пpочитать инфоpмацию из файла, котоpый был откpыт
    • FILE_SHARE_WRITE позволяет дpугим пpоцессам записывать инфоpмацию в откpытый файл.
    • CREATE_NEW Создание нового файла, если файла не существует.
    • CREATE_ALWAYS Создание нового файла. Функция пеpезаписывает файл, если он существует.
    • OPEN_EXISTING Окpытие существующего файла.
    • OPEN_ALWAYS Откpытие файла, если он существует, в пpотивном случае, функция создает новый файл.
    • TRUNCATE_EXISTING Откpытие файла и обpезание его до нуля байтов. Вызывающий функцию пpоцесс должен откpывать файл по кpайней меpе с доступом GENERIC_WRITE. Если файл не существует, функция не сpабатывает.
    • FILE_ATTRIBUTE_ARCHIVE Файл является аpхивным файлом. Пpиложения используют этот аттpибут для бэкапа или удаления.
    • FILE_ATTRIBUTE_COMPRESSED Файл или диpектоpия сжаты. Для файла это означает, что вся инфоpмация в файле зааpхивиpована. Для диpектоpии это означает, что сжатие подpазумевается по умолчанию для создаваемых вновь файлов и поддиpектоpий.
    • FILE_ATTRIBUTE_NORMAL У файла нет дpугих аттpибутов. Этот аттpибут действителен, только если исопльзуется один.
    • FILE_ATTRIBUTE_HIDDEN Файл спpятан. Он не включается в обычные листинги диpектоpий.
    • FILE_ATTRIBUTE_READONLY Файл только для чтения. Пpиложения могут читать из файла, но не могут писать в него или удалить его.
    • FILE_ATTRIBUTE_SYSTEM Файл - часть опеpационной системы или используется только ей.
    invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,MEMSIZE

    Когда файл откpыт, мы pезеpвиpует блок память для использования функциями ReadFile и WriteFile. Мы указываем флаг GMEM_MOVEABLE, чтобы позволить Windows пеpемещать блок памяти, чтобы уплотнять последнюю.

    Когда GlobalAlloc возвpащает положительный pезультат, eax содеpжит хэндл заpезеpвиpованного блока памяти. Мы пеpедаем этот хэндл функции GlobalLock, котоpый возвpащает указатель на блок памяти.

    invoke ReadFile,hFile,pMemory,MEMSIZE-1,ADDR SizeReadWrite,NULL

    В этой месте у нас нет необходимости деpжать файл откpытым, так как нашей целью является запись модифициpованных данных из edit control'а в дpугой файл, а не в оpигинальный. Поэтому мы закpываем файл функцией CloseHandle, пеpедав ей в качестве паpаметpа хэндл файла. Затем мы откpываем блок памяти и освобождаем его. В действительности, вам не нужно освобождать ее сейча, вы можете использовать этот же блок во вpемя опеpации сохpанения. Hо в демонстpационных целях я освобождаю ее сейчас.

    Когда на экpане отобpажается окно откpытия файла, фокус ввода сдвигается на него. Поэтому, когда это окно закpывается, мы должны пеpедвинуть фокус ввода обpатно на edit control.

    Это заканчивает опеpацию чтения из файла. В этом месте пользователь должен отpедактиpовать содеpжимое edit control'а. И когда он хочет сохpанить данные в дpугой файла, он должен выбpать File/Save, после чего отобpазиться диалоговое окно. Создание окна сохpанения файла не слишком отличается от создание окна откpытия файла. Фактически, они отличаются только именем функций. Вы можете снова использовать большинство из паpаметpов стpуктуpы ofn, кpоме паpаметpа Flags.

    В нашем случае, мы хотим создать новый файл, так чтобы OFN_FILEMUSTEXIST и OFN_PATHMUSTEXIST должны быть убpаны, иначе диалоговое окно не позволит нам создать файл, котоpый уже не существует.

    Паpаметp dwCreationDistribution функции CreateFile должен быть установлен в CREATE_NEW, так как мы хотим создать новый файл.
    Оставшийся код пpактически одинаков с тем, что используется пpи создании окна откpытия файла, за исключением следующего:

    invoke SendMessage,hwndEdit,WM_GETTEXT,MEMSIZE-1,pMemory invoke WriteFile,hFile,pMemory,eax,ADDR SizeReadWrite,NULL

    Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

    Определяет, существует ли заданный файл.

    Параметры

    Возвращаемое значение

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

    Примеры

    В следующем примере определяется, существует ли файл.

    Комментарии

    ExistsМетод не должен использоваться для проверки пути. Этот метод просто проверяет, существует ли файл, указанный в path Exists. Передача недопустимого пути для Exists возврата false . Чтобы проверить, содержит ли путь недопустимые символы, можно вызвать GetInvalidPathChars метод, чтобы получить символы, недопустимые для файловой системы. Можно также создать регулярное выражение для проверки того, является ли путь допустимым для вашей среды. Примеры допустимых путей см. в разделе File .

    Чтобы проверить, существует ли каталог, см Directory.Exists . раздел.

    Имейте в виду, что другой процесс потенциально может сделать что-то с файлом в промежутке между вызовом Exists метода и выполнением другой операции с файлом, например Delete .

    path Параметр может указывать сведения относительного или абсолютного пути. Сведения об относительном пути интерпретируется как относительно текущего рабочего каталога. Сведения о получении текущего рабочего каталога см. в разделе GetCurrentDirectory .

    Если path описывает каталог, этот метод возвращает false . Конечные пробелы удаляются из path параметра перед определением наличия файла.

    Метод возвращает значение, если возникла Exists false Ошибка при попытке определить, существует ли указанный файл. Это может произойти в ситуациях, когда вызываются такие исключения, как передача имени файла с недопустимыми символами или слишком много символов, неудачный или отсутствующий диск или если вызывающий объект не имеет разрешения на чтение файла.

    Я хотел бы найти самый быстрый способ проверить, существует ли файл в стандартном c/" >C++11, C++ или C. У меня есть тысячи файлов, и прежде чем что-то делать на них, мне нужно проверить, все ли они существуют. Что я могу написать вместо /* SOMETHING */ в следующей функции?

    Ну, я собрал тестовую программу, которая запускала каждый из этих методов 100 000 раз, наполовину на файлах, которые существовали, и наполовину на файлах, которые не существовали.

    результаты за общее время выполнения 100 000 вызовов в среднем за 5 запусков,

    на stat() функция обеспечила лучшую производительность в моей системе (Linux, скомпилированный с g++ ), со стандартным fopen звоните лучше всего, если вы по какой-то причине отказываетесь использовать функции POSIX.

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

    Примечание : В C++14, и как только файловая система TS будет закончено и принято, решение будет использовать:

    и так как C++17, только:

    Это зависит от того, где эти файлы находятся. Например, если все они должны находиться в одном каталоге, вы можете прочитать все записи каталога в хэш-таблицу, а затем проверить все имена в хэш-таблице. Это может быть быстрее в некоторых системах, чем проверять каждый файл по отдельности. Самый быстрый способ проверить каждый файл индивидуально зависит от вашей системы . если вы пишете ANSI C, самый быстрый способ - fopen потому что это единственный способ (файл может существовать, но не открываем, но вы, вероятно, действительно хотите открыть, если вам нужно "что-то сделать"). C++, POSIX, Windows предлагают дополнительные опции.

    пока я здесь, позвольте мне указать на некоторые проблемы с вашим вопросом. Вы говорите, что хотите самый быстрый способ и что у вас есть тысячи файлов, но затем вы просите код для функции для тестирования одного файла (и эта функция действительна только на C++, а не на C). Это противоречит вашим требованиям, делая предположение о решении . случай проблема XY. Вы также говорите "в стандартном c++11 (или)C++(или) c" . которые все разные, и это также несовместимо с вашим требованием к скорости . самое быстрое решение - адаптация кода к целевой системе. Несоответствие в вопросе подчеркивается тем фактом, что вы приняли ответ, который дает решения, зависящие от системы и не являющиеся стандартными C или c++.

    для тех, кто любит boost:

    без использования других библиотек мне нравится использовать следующий фрагмент кода:

    В лекции рассматривается использование функций библиотеки (C++): CreateFile(), CopyFile(), MoveFile(), DeleteFile(), ReadFile(), WriteFile(), UnlockFile(), LockFile() и CloseHandle().

    Материалы по данной теме имеются так же в лекции про файлы.

    Создание файлов
    Для создания нового или открытия существующего файла используется функция CreateFile. При использовании функции CreateFile необходимо указать, предполагается чтение или запись в файл или и то и другое. Также необходимо указать, необходимые действия в случае наличия файла на диске или его отсутствия (например, перезаписывать файл, если он существует и создавать новый, если – нет). Также функция CreateFile позволяет указать возможность разделения файла с другими приложениями (одновременного чтения/записи нескольких приложений в файл). Если некоторое приложение монополизировало доступ к файлу на чтение и/или запись, то никакое другое приложение не сможет читать и/или писать в файл, пока первое его не закроет.

    Операционная система присваивает каждому открытому файлу уникальный идентификатор (дескриптор, file handle), который может быть использован при обращениях к файлу для записи, чтения и получения информации о файле. Дескриптор действителен до тех пор, пока файл не закрыт. Приложение может наследовать дескрипторы файлов от процесса, который его запустил (если дескрипторы наследуемые). Функция CreateFile среди прочих объектов позволяет обращаться к файлам и каналам (pipes). При обращении к каналам функция CreateFile позволяет создавать клиентское подключение к именованным каналам, находящимся в режиме ожидания подключения. Серверная часть канала создаётся функцией CreateNamedPipe. Одно приложение может создавать множество клиентских подключений к каналу, но к одному экземпляру канала может подключаться только одно приложение (Стоит отметить, что возможно существование нескольких экземпляров именованных каналов с одинаковыми именами).
    Функция CreateFile имеет следующий прототип:
    HANDLE CreateFile(
    LPCTSTR lpFileName, // file name
    DWORD dwDesiredAccess, // access mode
    DWORD dwShareMode, // share mode
    LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
    DWORD dwCreationDisposition, // how to create
    DWORD dwFlagsAndAttributes, // file attributes
    HANDLE hTemplateFile // handle to template file
    ); dwDesiredAccess:
    [in] Описание желаемого режима доступа к файлу. Существует возможность передачи большого количества различных флагов. Нас интересуют флаги GENERIC_READ, GENERIC_WRITE и их объединение. При доступе к каналам следует учитывать режим создания канала сервером. Если сервер создал канал для записи, то клиент открывает его для чтения и наоборот. Если сервер создал канал для чтения и записи, то клиент может открыть его как для чтения, так и для записи.
    dwShareMode:
    [in] Определяет режим разделения объекта
    0 – приложение открывает файл для монопольного доступа. Последующие обращения на открытие данного файла будут безуспешными, пока данных дескриптор не будет закрыт. Для разделения доступа к файлу могут использоваться следующие ключи (один или вместе):
    FILE_SHARE_READ – разрешены лишь последующие операции открытия только на чтение.
    FILE_SHARE_WRITE – разрешены лишь последующие операции открытия только на запись.
    lpSecurityAttributes
    [in] Указатель на сруктуру SECURITY_ATTRIBUTES, которая определяет возможность наследования дескриптора дочерними процессами. Можно передавать NULL – это значит, что дескриптор не может быть наследован (для наших приложений этого достаточно).

    dwCreationDisposition:
    [in] Определяет то, какие действия необходимо предпринять в случаях, если файл существует и если файл не существует. Этот параметр должен иметь одно из следующих заначений:
    Значение Пояснение
    CREATE_NEW Создаёт файл. Вызов заканчивается неудачей, если файл существует.
    CREATE_ALWAYS Создаёт новый файл. Если файл существует, то его содержимое и атрибуты будут стёрты.
    OPEN_EXISTING Открытие файла. Если файл не существует, то вызов закончится неудачей.
    OPEN_ALWAYS Открывает файл. Если файл не существует, то он будет создан.
    TRUNCATE_EXISTING Открывает файл, размер которого обнуляется. Файл должен открываться как минимум с режимом доступа GENERIC_WRITE. Если файл не существует, то вызов будет неудачен.

    dwFlagsAndAttributes:
    [in] Позволяет задавать файловые атрибуты (только для чтения, скрытый, системный и пр.). Также позволяет сообщать операционной системе желаемое поведение при работе с файлами. Например, запись в файл без буферизации (FILE_FLAG_NO_BUFFERING и FILE_FLAG_WRITE_THROUGH); оптимизация для неупорядоченного доступа (FILE_FLAG_RANDOM_ACCESS); открытие для асинхронного ввода/вывода (FILE_FLAG_OVERLAPPED).

    Возвращаемое значение:
    Если вызов успешен, возвращается дескриптор открытого файла. Если вызов неудачен, возвращается константа INVALID_HANDLE_VALUE. Код ошибки можно получить вызовом функции GetLastError. Подробную информацию об ошибке (по её коду) можно получить вызовом функции FormatMessage.

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

    BOOL CopyFile(
    LPCTSTR lpExistingFileName, // имя существующего файла
    LPCTSTR lpNewFileName, // имя нового файла
    BOOL bFailIfExists // действие, если файл существует TRUE – ошибка
    // FALSE - перезаписывать
    );

    В случае успеха возвращается ненулевое значение.

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

    BOOL MoveFile(
    LPCTSTR lpExistingFileName, // имя файла
    LPCTSTR lpNewFileName // новое имя файла
    );

    В случае успеха возвращается ненулевое значение.

    Для удаления существующих файлов используется функция DeleteFile:

    BOOL DeleteFile(
    LPCTSTR lpFileName // имя удаляемого файла
    );

    Чтение/запись в файл:
    Каждый открытый файл имеет файловый указатель (file pointer), который указывает позицию следующего файла, который будет записан/прочтен. При открытии файла его файловый указатель перемещается на начало файла. После прочтения/записи очередного файла система перемещает файловый указатель. Файловый указатель можно перемещать, используя функцию SetFilePointer.
    Для чтения/записи в файл используются функции ReadFile и WriteFile, при этом необходимо, чтобы файл был открыт на чтение и на запись соответственно.

    Функция ReadFile читает из файла указанное количество символов, начиная с позиции, обозначенной файловым указателем. При синхронном (в противоположность асинхронному) чтении файловый указатель сдвигается на фактически прочитанное количество байт.

    BOOL ReadFile(
    HANDLE hFile, // дескриптор файла
    LPVOID lpBuffer, // буфер данных
    DWORD nNumberOfBytesToRead, // количество байт для прочтения
    LPDWORD lpNumberOfBytesRead, // количество фактически прочитанных байт
    LPOVERLAPPED lpOverlapped // указатель на структуру, используемую при
    // асинхронном чтении
    ); hFile:
    [in] Дескриптор читаемого файла. Должен быть открыт с доступом GENERIC_READ.
    lpBuffer:
    [out] Указатель на буфер, принимающий данные из файла.
    nNumberOfBytesToRead:
    [in] Задаёт количество байт, которые необходимо прочитать из файла.
    lpNumberOfBytesRead:
    [out] Указатель на переменную, которая принимает количество реально прочитанных байт.
    lpOverlapped:
    [in] Укзатель на структуру OVERLAPPED. При не асинхронном доступе следует передавать NULL.

    Возвращаемое значение:
    Если выполнение функции произошло успешно, то возвращается ненулевое значение. Если возвращено ненулевое значение, но прочитано 0 байт, значит файловый указатель стоял на конце файла перед операцией чтения.

    Функция WriteFile записывает в файл данные, начиная с позиции, обозначенной файловым указателем. При синхронной (в противоположность асинхронному) записи файловый указатель сдвигается на фактически записанное количество байт.

    BOOL WriteFile(
    HANDLE hFile, // дескриптор файла
    LPCVOID lpBuffer, // буфер данных
    DWORD nNumberOfBytesToWrite, // количество байт для записи
    LPDWORD lpNumberOfBytesWritten,// количество фактически записанных байт
    LPOVERLAPPED lpOverlapped // указатель на структуру, используемую при
    // асинхронном чтении
    );
    hFile:
    [in] Дескриптор файла, в который производится запись. Должен быть открыт с доступом GENERIC_WRITE.
    lpBuffer:
    [in] Указатель на буфер, содержащий данные, которые необходимо записать.
    nNumberOfBytesToWrite:
    [in] Задаёт количество байт, которые необходимо записать в файл.
    lpNumberOfBytesWritten:
    [out] Указатель на переменную, которая принимает количество реально записанных байт.
    lpOverlapped:
    [in] Укзатель на структуру OVERLAPPED. При не асинхронном доступе следует передавать NULL.
    Возвращаемое значение:
    Если выполнение функции произошло успешно, то возвращается ненулевое значение.

    Блокировка файлов:
    Т.к. система позволяет более чем одному приложению открывать файл и писать в него, приложения не должны одновременно писать в одну область файла. Эта проблема может быть решена путем временного блокирования части файла. Функция LockFile позволяет приложению получить в монопольное пользования определённое количество байт в файле. Отрезок заблокированных байт может выходить за текущий конец файла. Все попытки сторонних приложений обратиться к заблокированному участку файла потерпят неудачу.
    Приложение может файл с помощью функции UnlockFile .
    BOOL LockFile(
    HANDLE hFile, // дескриптор файла
    DWORD dwFileOffsetLow, // младшее слово смещения начала отрезка
    DWORD dwFileOffsetHigh, // старшее слово смещения начала отрезка
    DWORD nNumberOfBytesToLockLow, // младшее слово длины отрезка
    DWORD nNumberOfBytesToLockHigh // старшее слово длины отрезка
    );
    hFile:
    [in] Дескриптор файла, в который производится запись. Должен быть открыт с доступом GENERIC_READ или GENERIC_WRITE (или обоими).
    dwFileOffsetLow:
    [in] Определяет младшее слово смещения начала блокируемого отрезка относительно начала файла.
    dwFileOffsetHigh:
    [in] Определяет старшее слово смещения начала блокируемого отрезка относительно начала файла. Не равно нулю, если смещение относительно начала более чем 232 байт.
    nNumberOfBytesToLockLow:
    [in] Определяет младшее слово длины блокируемого отрезка.
    nNumberOfBytesToLockHigh:
    [in] Определяет старшее слово длины блокируемого отрезка. Не равно нулю, если длина отрезка более 232 байт или 4 ГБ.

    Возвращаемое значение:
    Если выполнение функции произошло успешно, то возвращается ненулевое значение.
    Блокирование предоставляет процессу монопольный доступ к отрезку файла. Файловые блокировки не наследуются. Остальные процессы не могут ни читать, ни писать в заблокированную часть файла.

    Функция UnlockFile позволяет разблокировать участок файла, ранее заблокированный функцией LockFile .

    BOOL UnlockFile(
    HANDLE hFile, // дескриптор файла
    DWORD dwFileOffsetLow, // младшее слово смещения начала отрезка
    DWORD dwFileOffsetHigh, // старшее слово смещения начала отрезка
    DWORD nNumberOfBytesToUnlockLow, // младшее слово длины отрезка
    DWORD nNumberOfBytesToUnlockHigh // старшее слово длины отрезка
    );
    Параметры данной функции аналогичны параметрам функции LockFile.

    Возвращаемое значение:
    Если выполнение функции произошло успешно, то возвращается ненулевое значение.
    Отрезок файла, который разблокируется функцией UnlockFile должен в точности соответствовать отрезку, заблокированному функцией LockFile. Например, две соседних части файла не могут быть заблокированы по отдельности, а разблокированы как единое целое. Процесс не должен завершать выполнение, имея заблокированные части файлов. Файловый дескриптор, для которого есть заблокированные отрезки, не должен закрываться.

    Для оптимального использования ресурсов операционной системы приложение должно закрывать ненужные файлы с помощью функции CloseHandle. Файлы, открытые на момент завершения приложения, закрываются автоматически.

    BOOL CloseHandle(
    HANDLE hObject // Дескриптор объекта (файла, канала и пр.)
    );

    Возвращаемое значение:
    Если выполнение функции произошло успешно, то возвращается ненулевое значение.

    Читайте также: