Принудительное чтение на диске с помощью std::ifstream вместо файлового кэша

#c #windows #caching #std #ifstream

#c #Windows #кэширование #std #ifstream

Вопрос:

У меня есть программа, которая загружает данные из файла с помощью std::ifstream и сохраняет данные в структуре. После этого я проверяю, были ли нужные мне данные в файле. Если это не так, я прошу пользователя изменить файл и нажать клавишу. Затем я перезагружаю файл. Проблема в том, что даже если пользователь изменил файл, я всегда получаю одни и те же данные в файле, потому что файл, похоже, кэшируется в приложении. Я видел, что в win32 API можно использовать флаг FILE_FLAG_NO_BUFFERING, чтобы избежать использования буферизованной копии при чтении файла, но я хотел бы использовать эту функцию с std::ifstream . Есть ли какой-либо способ использовать дескриптор, созданный через win32 api, с помощью ifstream или в любом случае принудительно использовать его непосредственно в std::ifstream?

Вот «упрощенный» пример кода:

 SomeStructure  s = LoadData(fileName);
while(!DataValid(s))
    s = LoadData(fileName);


SomeStructure LoadData(const std::stringamp; fileName)
{
    std::ifstream fileStream;
    while(!OpenFileRead(fileName, fileStream))
    {
        std::cout<<"File not found, please update it";
        fileStream.close();
        //Wait for use input
        std::string dummy;
        std::getline(std::cin, dummy);
    }
    //... Read file, fill structure, and return
    std::string line;   
    while(std::getline(fileStream, line) amp;amp; line!="")
    {
        //At this point, I can see that line is wrong
        StringArray namedatearray=Utils::String::Split(line, "|");
        assert(namedatearray.size()==2);
        //Add data to my structure ( a map)
     }
     fileStream.close();
     //return structure
}

bool OpenFileRead(const std::stringamp; name, std::fstreamamp; file)
{    
    file.open(name.c_str(), std::ios::in);
    return !file.fail();
}
 

Спасибо.

Редактировать: Конечно, это была ошибка, потому что у меня было два раза один и тот же файл по двум очень похожим путям. Просмотр дескриптора файла, открытого в process Explorer (а не относительный путь к файлу, заставил меня его найти).

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

1. Небуферизованный ввод-вывод здесь не имеет никакого отношения. У вас либо неисправный код записи, либо неисправный код чтения.

2. Если проблема заключается в кэшировании в приложении, как вы утверждаете, то небуферизованный ввод-вывод вам не поможет, потому что небуферизованный ввод-вывод означает отсутствие буферизации в ядре . Это не имеет никакого отношения к кэшированным данным приложения. И вы вряд ли сможете ifstream работать с небуферизованным дескриптором, потому что когда вы создаете объект с ограничениями, вы должны убедиться, что все, кто использует объект, понимают эти ограничения .

3. Как вы изменяете файл? Многие вещи, которые мы считаем «модифицирующими» файл, на самом деле вообще не изменяют файл, а вместо этого заменяют файл новым, измененным файлом.

4. Что касается кода записи, то изменения выполняются с помощью обычного старого блокнота (и сохраняются сразу после). Что касается части чтения, я добавил ее в код.

Ответ №1:

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

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

Тот факт, что ОС использует файловые буферы для повышения производительности диска, обычно не виден на уровне приложений. Пока вы просматриваете один и тот же файл, ОС знает, что пользователь обновил файл, и если вы снова откроете его, вы увидите измененные данные. Если у данных даже не было возможности сбросить данные на диск, это не повлияет на ваше приложение.

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

1. 1) Ну, пользователь — это я, и есть только версия файла, поэтому я уверен, что меняю правильную версию файла. Что касается остального, после успешного открытия моего файла я перехожу к файлу построчно и вижу, что данные похожи на старую версию файла, а не на новую. Что заставляет меня думать, что это связано с буферизацией приложения, так это то, что если я перезагружу свое приложение, оно прочитает новую версию. Что касается изменения файла, это делается с помощью блокнота (и сохраняется сразу после). Тем не менее, довольно странно, что я страдаю от такой проблемы на уровне приложений…

2. Возможно, в вашем приложении есть другой дескриптор файла, открытого где-то еще? Это может помочь объяснить, почему перезагрузка вашего приложения работает. Когда ваше приложение закрывается, все открытые вами дескрипторы закрываются.

3. Хм … это немного смущает… При визуализации дескрипторов моей программы (с помощью process Explorer) я понял, что теперь у меня было 2 версии файла по двум почти идентичным путям (у меня были ошибки при обновлении моего локального репозитория до tortoise svn до 1.7, поэтому мне пришлось создать новый и все еще использовать решение firstрепозиторий).

4. @Jean-PhilippeJodoin: Не беспокойтесь, это случается со всеми. 🙂