Повторное открытие закрытого файлового потока

#c #c 11 #visual-c #c 14

#c #c 11 #visual-c #c 14

Вопрос:

Рассмотрим следующий код,

 auto fin = ifstream("address", ios::binary);
if(fin.is_open()) 
    fin.close()
for(auto i = 0; i < N;   i){
    fin.open()
    // ....
    // read (next) b bytes...
    // ....
    fin.close()
    // Some delay
}
  

Приведенный выше код не может быть реализован на C , который я знаю, но я хотел бы знать, возможно ли это сделать?

Вот мои требования:

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

Разъяснение

  • Файлы, с которыми я работаю, имеют большой размер, и в определенный момент времени другие потоки из сторонних библиотек могут решить (повторно) переместить их. Открытый поток предотвратит такие действия.
  • Непрерывное чтение большого файла замедлит работу системы.

Комментарии:

1. Потоки работают не так. Зачем закрывать его, если вы хотите, чтобы он был открыт и позиционирован?

2. @BoPersson Файлы, с которыми я работаю, имеют большой размер, и в какой-то момент другие потоки из сторонних библиотек могут решить удалить их. Открытый поток предотвратит это действие, и эти потоки могут завершиться сбоем.

3. Здесь вы настраиваетесь на кошмар параллелизма. Рекомендую переосмыслить.

4. Удалил мой ответ, поскольку я недостаточно помню C , чтобы продолжить отвечать. Вы всегда можете создать функцию, которая принимает аргументы конструктора и возвращает новую функцию, которая принимает поток, и создает новую там, где остановилась старая. Вероятно, самый простой способ сделать то, чего вы пытаетесь достичь.

5. @Carcigenicate Я ценю время, которое вы посвятили ответу. Спасибо. Я взял идею из того, что вы упомянули.

Ответ №1:

Необходимость

Действительно, файл не может быть удален другим процессом, пока поток сохраняет его открытым.

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

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

Решение

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

    auto mypos = ifs.tellg();  // saves position.  
                              // Should flag be saved as well ? and what about gcount ?
   ifs.close();  

   ...

   if (! ifs.is_open()) {
       ifs.open(myfilename, myflags);  // open again !  
       if (! ifs) { 
           // ouch ! file disapeared ==> process error 
       }
       ifs.seekg(mypos);              // restore position 
       if (! ifs) { 
           // ouch ! position no longer reachable  ==> process error 
       }
   }
  

Конечно, вы не хотели бы повторять этот код когда-либо и когда-либо. И было бы не так приятно, если бы внезапно появилось много глобальных переменных для отслеживания состояния потока. Но вы могли бы очень легко инкапсулировать его в класс-оболочку, который позаботится о сохранении и восстановлении состояния потока с использованием существующих стандартных операций.

Комментарии:

1. Даже если файл открыт, он может быть обрезан до нулевого размера другими процессами, и его запись в каталоге может быть удалена. Какова предполагаемая операционная система?

2. @HeikoBloch да, и мы не будем решать здесь все проблемы OP. Я думаю, что OP нацелен на Windows из-за тега «visual C »

3. Спасибо. Вопросы, которые вы задали, я имел в виду. К сожалению, все риски, о которых вы упомянули, существуют, и у меня не было лучшего решения, чем то, которое вы дали. Кажется, другого или лучшего решения нет. Еще раз спасибо.