C++: открытие файла в неисключительном режиме

Мне нужно разработать приложение, которое анализирует файл журнала и отправляет определенные данные на сервер. Он должен работать как в Linux, так и в Windows.

Проблема возникает, когда я хочу протестировать систему прокрутки журналов (которая добавляет .1 к имени, создает новый с тем же именем). В Windows (еще не тестировал в Linux) я не могу переименовать файл, который я открыл с помощью std :: ifstream () (эксклюзивный доступ?), Даже если я открываю его в «режиме ввода» (ios :: in) .

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
6 671
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

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

Семантика файловой системы Win32 требует, чтобы переименованный файл не был открыт (в любом режиме) во время переименования. Вам нужно будет закрыть файл, переименовать его, а затем создать новый файл журнала.

Семантика файловой системы Unix позволяет вам переименовывать открытый файл, потому что имя файла является просто указателем на индексный дескриптор.

Если вы читаете только из файла, я знаю, что это можно сделать с помощью Windows API CreateFile. Просто укажите FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE в качестве входных данных для dwShareMode.

К сожалению, это не кроссплатформенный. Но что-то подобное может быть и для Linux.

См. Msdn для получения дополнительной информации о CreateFile..

Обновлено: Просто небольшое примечание о комментарии Грега Хьюгилла. Я только что протестировал материал FILE_SHARE * (тоже будьте уверены на 100%). И есть возможность как удалять, так и переименовывать файлы в окнах, если вы открываете только для чтения и указываете параметры FILE_SHARE *.

Ответ принят как подходящий

Is there a way to open file in a non-exclusive way,

Да, используя Win32, передавая различные флаги FILE_SHARE_Xxxx в CreateFile.

is it cross platform?

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

Из-за раздражающих проблем обратной совместимости (приложения DOS, будучи однозадачными, предполагают, что ничто не может удалить файл из-под них, то есть они могут fclose (), а затем fopen () без каких-либо сбоев; Win16 сохранил это предположение, чтобы сделать легче переносить приложения DOS, Win32 сохранил это предположение, чтобы упростить перенос приложений Win16, и это ужасно), по умолчанию Windows открывает только файлы.

Базовая инфраструктура ОС поддерживает удаление / переименование открытых файлов (хотя я считаю, что у нее есть ограничение, что файлы с отображением памяти не могут быть удалены, что, я думаю, не является ограничением, обнаруженным в * nix), но семантика открытия по умолчанию - нет.

C++ не имеет ни малейшего представления об этом; Операционная среда C++ во многом такая же, как и операционная среда DOS - другие приложения не работают одновременно, поэтому нет необходимости контролировать совместное использование файлов.

Я бы позаботился о том, чтобы вы не оставляли файлы открытыми. Это приводит к странным вещам, например, если ваше приложение вылетает из строя. Что бы я сделал:

  1. Абстрагируйте (чтение / запись / переход к новому файлу) в один класс и организуйте закрытие файла, когда вы хотите перейти к новому файлу в этом классе. (это самый изящный способ, и поскольку у вас уже есть код пролонгации, вы уже на полпути.)
  2. Если у вас должно быть несколько точек доступа для чтения / записи, вам нужны все функции fstreams и вы не хотите писать полную оболочку, тогда единственное кроссплатформенное решение, о котором я могу думать, - это всегда закрывать файл, когда он вам не нужен. , и пусть код пролонгации пытается получить монопольный доступ к файлу несколько раз, когда ему нужно пролистать, прежде чем отказаться.

Другие вопросы по теме