Проверить существует ли файл c

Обновлено: 05.07.2024

Я работаю над приложением. Это приложение должно получать резюме от пользователей, поэтому мне нужен код, чтобы проверить, существует файл или нет.

Вы можете определить, существует ли указанный файл, используя метод Exists в File класс в пространстве имен System.IO :

Пример:

Я сделал что-то подобное, чтобы проверить, существует ли изображение перед его отображением.

Простой ответ заключается в том, что вы не можете - вы не сможете проверить файл на их компьютере с веб-сайта ASP, так как это может быть опасным для них.

Вы должны предоставить им элемент управления загрузкой файлов - и вы мало что можете сделать с этим элементом управления. По соображениям безопасности javascript не может по-настоящему его трогать.

Вы можете использовать:

Пока не могу комментировать, но я просто хотел не согласиться /уточнить с erikkallen .

Вы не должны просто поймать исключение в описанной вами ситуации. Если вы ЗНАЕТЕ, что файл должен быть там, и из-за какого-то исключительного случая это не так, тогда было бы приемлемо просто попытаться получить доступ к файлу и перехватить любое возникшее исключение.

Однако в этом случае вы получаете данные от пользователя и у вас мало причин полагать, что файл существует. Здесь вы всегда должны использовать File.Exists ().

Я знаю, что это клише, но вы должны использовать исключения только для исключительного события, а не как часть обычного потока вашего приложения. Это дорого и делает код более трудным для чтения /отслеживания.

Все эти ответы предполагают, что проверяемый файл находится на стороне сервера. К сожалению, нет чугунного способа гарантировать, что файл существует на стороне клиента (например, если вы загружаете резюме). Конечно, вы можете сделать это в Javascript, но вы все еще не уверены на 100% на стороне сервера.

В дополнение к использованию File.Exists() вам может быть лучше просто попытаться использовать файл и перехватить любое выброшенное исключение. Файл может не открыться из-за других вещей, кроме несуществующих.

Это может помочь вам.

Я написал этот код в vb, и он отлично работает, чтобы проверить, существует файл или нет для контроля загрузки файла. попробуй

Как определить, есть ли файл на диске?

Библиотечная функция access позволяет определять режим доступа к файлу, а если второй параметр mode равен нулю, то определяется только существование файла.

Хотя эта функция и не входит в стандарт C/C++, тем не менее, она присутствует в компиляторах Visual C++, Borland C++, Watcom C++ и многих других в неизменном виде.

Способ 2 (_findfirst)

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

С помощью этого способа можно определять не только существование отдельного файла, но также и группы файлов, соответствующей заданной маске. А если задать маску как "*.*" , то можно узнать есть ли файлы в заданной директории.

Способ 3 (GetFileAttributes)

Функция GetFileAttributes Win32 API возвращает атрибуты для заданного файла или каталога. В случае ошибки возвращается значение 0xFFFFFFFF.

Этот способ используется во многих примерах из MSDN, что позволяет предположить, что это штатный способ для решения нашей задачи в Win API. Кроме того, это самый быстрый из приведенных здесь способов.

Способ 4 (FindFirstFile)

Этот способ аналогичен способу 2 с той лишь разницей, что для достижения результата используется функция Win32 API.

Способ 5 (MFC)

MFC содержит класс-обёртку для функций Find. API. Мы вполне можем использовать этот класс.

Способ 6 (WTL)

Среди прочих классов, подобных MFC, WTL также содержит и CFindFile .Следовательно, этот способ внешне ни чем не отличается от предыдущего, кроме того, что не требует MFC.DLL. На самом деле этот способ намного быстрее предыдущего. Дело в том, что все функции класса CFindFile являются inline ,так что код, генерируемый компилятором, почти целиком совпадает с кодом для способа 4.

Способ 7 (PathFileExists)

Ещё один способ из предложенных Александром Шаргиным - использование SHLWAPI Path API .

Правда у этого способа имеются определённые недостатки, которые значительно сужают его практическое применение:

  • Он не будет работать, если на компьютере не установлен Internet Explorer 4.0 или выше, что может быть вполне вероятно на компьютерах с ранними версиями Windows 95 и Window NT 4.0.
  • Функция PathFileExists() не поддерживает UNC имена файлов.

Способ 8 (CreateFile)

Самый очевидный и самый громоздкий способ.

Способ 9 (Pure C++ метод std::ifstream, ::ifstream)

Данный метод состоит в создании временного объекта класса ifstream .Если файл с указанным именем не существует то operator void *() этого класса возвращает NULL pointer - иначе возвращается указатель на сам созданный объект ( this ). Это значение проверяется на NULL pointer - и . все.

. вернее почти все =)

В данном коде ifstream это typedef basic_ifstream < char , char_traits < char >> ifstream; если же Вы пользуетесь старыми заголовочными файлами (с расширением .h) - то для Вас ifstream - это никакой не typedef - а самый настоящий класс. И все было бы прекрасно - если бы не одно но - в этом случае конструктор с именем файла в качестве параметра СОЗДАСТ файл (если он не существует) и в любом случае, проверка на существование файла даст положительный результат. Дело в том, что для "старого" ifstream 'а надо явно указывать что НЕ надо создавать файл через добавление флага ios:: nocreate во втором параметре конструктора. А вот и сам код для такого случая:

Данный метод хорош тем что он 100% портабелен - то есть используются только возможности самого языка С++ (в лице его стандартной библиотеки - которая является его частью).

Способ 11 (Script)

Ни один из перечисленных способов не будет работать из .html документа. Зато из скрипта доступен Scripting.FileSystemObject и нам этого достаточно.

Мы вполне можем использовать Scripting.FileSystemObject и в COM-модуле:

Фактически, это очень извращенный способ вызова все той же функции access() из способа 1, с той разницей, что FileSystemObject работает с именами файлов в UNICODE и под WindowsNT/2k передает имя файла напрямую, а под Windows 9x/Me (и даже 3.1 с интернет эксплорером!) сам преобразовывает его в ANSI.

Есть ли лучший способ, чем просто попытаться открыть файл?

Я думаю, что я дам ответ на метод доступа, несмотря на то, что метод stat является очень разумной альтернативой, доступ выполняет свою работу. Вы действительно хотите проверить существование? Или вы хотите проверить и записать файл, если он еще не существует. Если это так, см. Мой ответ ниже, для версии, которая не страдает от условий гонки. я не вижу - что не так с этим способом fopen / fclose? @ JohannesSchaub-litb: одна из особенностей метода fopen() / fclose() заключается в том, что вы не сможете открыть файл для чтения, даже если он существует. Например, /dev/kmem существует, но большинство процессов не может открыть его даже для чтения. /etc/shadow еще один такой файл. Конечно, оба stat() и access() полагаются на возможность доступа к каталогу, содержащему файл; все ставки отключены, если вы не можете сделать это (нет разрешения на выполнение для каталога, содержащего файл). if (file = fopen(fname, "r")) даст предупреждение. Используйте круглые скобки в операторе if if ((file = fopen(fname, "r")))

Посмотрите на access() функцию, найденную в unistd.h . Вы можете заменить свою функцию на

Вы также можете использовать R_OK , W_OK и X_OK вместо того F_OK чтобы проверить для чтения разрешения, разрешений на запись и выполнение разрешения (соответственно) , а не существование, и вы можете или любые из них вместе (т.е. проверить , как для чтения и разрешения записи с помощью R_OK|W_OK )

Обновление : обратите внимание, что в Windows вы не можете использовать W_OK надежный тест для разрешения записи, так как функция доступа не учитывает DACL. access( fname, W_OK ) может вернуть 0 (успех), поскольку файл не имеет установленного атрибута только для чтения, но у вас все еще может не быть разрешения на запись в файл.

POSIX является стандартом ISO; это определяет доступ (). C - другой стандарт ISO; Это не. Есть ошибки, связанные с доступом (). Существует окно уязвимости TOCTOU (время проверки, время использования) между использованием access () и тем, что вы делаете позже. [. продолжение следует . ] [. продолжение . ] Скорее более эзотерически, в системах POSIX access () проверяет, является ли реальный UID и реальный GID, а не эффективным UID и эффективным GID. Это имеет значение только для setuid или setgid программ, но тогда это имеет большое значение, так как может дать «неправильный» ответ. Я наткнулся на этот вопрос, когда искал причину access() взлома моего кода. Я перешел с DevC ++ на CodeBlocks, и он перестал работать. Так что это не безошибочно; +1 больше к @Leffler. В большинстве случаев да (это нормально использовать access() для проверки существования файла), но в программах SUID или SGID даже это может быть неверно. Если проверенный файл находится в каталоге, к которому не может получить доступ настоящий UID или реальный GID, access() такой файл может не появиться, если он существует. Эзотерический и невероятный? Да.

Используйте stat как это:

и назовите это так:

@LudvigANorin: есть вероятность, что в таких системах access() также есть проблемы, и есть варианты, которые можно использовать для создания access() и stat() работы с большими файлами (более 2 ГБ). Может ли кто-нибудь из вас указать на документацию о сбое после 2 ГБ? Кроме того, какова альтернатива в таких случаях? @JonathanLeffler Не stat страдает от такой же уязвимости TOCTOU, как access ? (Мне не ясно, что было бы лучше.) Оба stat() и access() страдают от уязвимости TOCTOU (так же lstat() , но fstat() безопасно). Это зависит от того, что вы собираетесь делать, в зависимости от наличия или отсутствия файла. Использование правильных опций open() обычно является лучшим способом решения проблем, но может быть сложно сформулировать правильные варианты. См. Также обсуждения EAFP (Проще просить прощения, чем разрешения) и LBYL (Посмотри, прежде чем ты прыгнешь ) - см., Например, LBYL против EAFP в Java .

Обычно, когда вы хотите проверить, существует ли файл, это потому, что вы хотите создать этот файл, если он не существует. Ответ Грэма Перроу хорош, если вы не хотите создавать этот файл, но он уязвим для состояния гонки, если вы это сделаете: другой процесс может создать файл между вами, проверив, существует ли он, и вы фактически открываете его, чтобы записать в него , (Не смейтесь . это может иметь плохие последствия для безопасности, если созданный файл был символической ссылкой!)

Если вы хотите проверить существование и создать файл, если он не существует, атомарно, чтобы не было условий гонки, то используйте это:

Если вы собираетесь использовать O_CREAT, вам нужно предоставить режим (права доступа) в качестве третьего аргумента для open (). Также подумайте, следует ли использовать O_TRUNC, O_EXCL или O_APPEND. Джонатан Леффлер прав, этот пример требует, чтобы O_EXCL работал как написано. Кроме того, вам нужно указать режим в качестве третьего аргумента: open (блокировка, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR) Следует отметить, что это настолько безопасно, насколько файловая система совместима с POSIX; в частности, старые версии NFS имеют то же самое состояние гонки, которого O_EXCL должен был избегать! Существует обходной путь, задокументированный в open(2) (для Linux; страницы руководства вашей ОС могут отличаться), но он довольно уродлив и не может быть устойчивым к злоумышленнику. Обратите внимание, что для использования этого FILE* вам необходимо использовать метод posix fdopen(fd,"flags") для генерации FILE*

Да. Использование stat() . Смотрите справочную страницу для stat(2) .

stat() потерпит неудачу, если файл не существует, в противном случае, скорее всего, удастся. Если он существует, но у вас нет доступа на чтение к каталогу, в котором он существует, он также потерпит неудачу, но в этом случае произойдет сбой любого метода (как вы можете проверить содержимое каталога, который вы можете не видеть в соответствии с правами доступа? Просто не можешь)

О, как кто-то еще упоминал, вы также можете использовать access() . Однако я предпочитаю stat() , так как, если файл существует, он сразу же получит много полезной информации (когда он последний раз обновлялся, насколько он велик, владелец и / или группа, которой принадлежит файл, права доступа и т. Д.).

Я хотел бы найти самый быстрый способ проверить, существует ли файл в стандартном 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:

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

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