Вопрос

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

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

Существует ли кроссплатформенный способ открыть файл неисключительным способом?

Это было полезно?

Решение

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

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

является ли это кроссплатформенным?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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