Не сохранять данные внутри вашего исполняемого файла , но за его пределами
Есть ли способ создать [...] программу, которая [...]запрашивает входные данные [...], а затем сохраняет эти данные в этом .exe, когда я его закрываю?
Простого пути нет (но он вам не нужен).То, что вы хотите, связано с постоянством и проверкой приложения .
На практике вы, вероятно, хотите хранить данные в файле, а не в исполняемом файле (возможно, используя некоторыетекстовый формат, такой как JSON ) или в некоторой базе данных (возможно, такой простой, как некоторые sqlite , или взаимодействие с некоторыми RDBMS , такими как PostGreSQL ).Для таких вещей, как дни рождения и предпочтения в еде, файл базы данных sqlite
, вероятно, является хорошим подходом (см. Руководство по SQLite ).Приложите усилия к хорошему дизайну вашей схемы базы данных .
Таким образом, когда я открою ее снова, все эти данные все равно будут сохранены там
Эти данные все еще будут там, если вы сохраните их в каком-то файле (возможно, простом myappdata.sqlite
).Вы можете легко спроектировать свою программу для создания этого файла, если он не существует (это происходит только при первом запуске вашей программы; при следующих запусках ваша программа успешно прочитает эти данные из этого внешнего файла при запуске).
В большинстве современных операционных систем (прочитайте этот учебник , чтобы узнать больше об ОС), особенно Windows, MacOSX, Linux, Android, ..., исполняемый файл предполагается только для чтения.И он может работать в нескольких процессах одновременно (в таком случае, что должно произойти? Подумайте о свойствах ACID ).
Обычная практика - хранить данные вне исполняемого файла (большинство программ, включая ваш текстовый процессор, ваш компилятор, ваш веб-браузер, ... делают это).Вы не объясняете, почему вы хотите хранить некоторые данные в исполняемом файле, и это необычно и очень специфично для конкретной операционной системы и формата исполняемого файла (для Linux изучите внимательно elf (5) ...)
Я бы предложил сохранить данные в каком-то необязательном файле (или базе данных) - его путь к файлу может иметь некоторую постоянную по умолчанию для проводной связи и т. Д ....При запуске вы проверяете наличие этих данных (например, с помощью access (2) в POSIX или просто обрабатывая случай сбоя fopen
или sqlite3_open
и т. Д ....).Если он не существует, вы каким-то образом инициализируете данные вашей программы.При выходе (или экономии времени) вы записываете эти данные.Кстати, большинство программ делают это.
Обратите внимание, что в большинстве операционных систем и компьютеров программное обеспечение представляет собой не просто один исполняемый файл, а гораздо больше (например, необходимые библиотеки и зависимости, файлы конфигурации, файлы данных, * 1075).* автоматизация сборки сценарии, такие как Makefile
и т. д.).Его установка является хорошо идентифицированным техническим процессом (иногда довольно сложным), и менеджеры пакетов полезны.
Мне кажется, что без определенной мотивации, вам даже не следует пытаться хранить (изменяемые) данные (постоянно) в вашем исполняемом файле (это сложно, хрупко, поскольку очень зависит от ОС, компилятора и цепочки сборки,необычно и открывает уязвимости ).
Для полноты картины некоторые программы действительно записывают некоторые данные, переписывая свой исполняемый файл.В Linux GNU emacs
делает это (на практике, только во время процедуры установки) в своем файле unexec.c
(очень хрупкий, так как зависит от ОС и компилятора), но это оспаривается и, вероятно, исчезнет.
Многие другие системы разумно справляются с ортогональным постоянством: SBCL имеет некоторый примитив save-lisp-and-die
(обычно он сохраняется в каком-либо другом файле "изображения"). Poly / ML имеет некоторое export
средство .Система J.IAPratrat CAIA (см. этот документ и его блог ; архив с CAIA 2016 доступен - с разрешения - на my домашняя страница) может полностью восстановить весь код C и все необходимые данные (в тысячах файлов). FullPliant сохраняет свое состояние в хорошо организованном дереве файлов.Такие методы сохранения или контрольных точек связаны с сборкой мусора (поэтому вам следует прочитать руководство GC ) и используют методы и алгоритмы, близкие к копированию сбора мусора.
FWIW, мой текущий проект, bismon , ортогонально сохраняет всю свою кучу, но делает это вне основного исполняемого файла (в идеальном мире я хотел бы заново сгенерировать весь исходный код C или C ++это; я далек от этой цели).
Я рекомендую хранить ваше программное обеспечение в нескольких файлах: его исполняемый файл, связанный с ним исходный код C ++, его файлы данных (и, вероятно, гораздо больше зависимостей, то есть общихбиблиотеки или библиотеки DLL, файлы шрифтов и изображений, необходимые двоичные файлы и т. д.).Тогда вам не нужно перезаписывать свой исполняемый файл при сохранении вашего состояния.Поскольку вы упоминаете C ++ (который является , а не homoiconic ), вы можете сгенерировать код C ++ вашей системы (затем называемый Quine программой) с его постоянными данными (и оставьте перекомпиляцию всего, что сгенерировало C ++, системному компилятору C ++).Я также рекомендую сделать вашу самогенерирующую программу свободным программным обеспечением .(если вы сделаете это, было бы неплохо отредактировать ваш вопрос так, чтобы он указывал его URL).
В C ++ вы можете хранить данные внутри исполняемого файла (опять же, это плохая идея ,и я надеюсь убедить вас избегать такого подхода) следующим образом: вы добавляете один исходный файл на C или C ++ (например, mydata.cc
), который содержит только данные (например, некоторые большие const char data[]="... many lines of data ...";
) - кстати, Формат файла XBM может быть вдохновляющим.Вы сохраняете все остальные *.o
объектные файлы (в месте, известном вашей программе).Чтобы сохранить данные, вы регенерируете этот mydata.cc
файл (с новыми данными для вашего текущего состояния) при каждой операции сохранения, и, наконец, вы запускаете соответствующие команды (возможно, используя std :: system в вашем коде), чтобы скомпилировать mydata.cc
и связать его с сохраненным *.o
в новый исполняемый файл.Поэтому для каждой операции сохранения требуется перекомпиляция data.cc
и ее связывание с другими объектными файлами *.o
(и, конечно, компилятор и компоновщик C ++, возможно, с дополнительными инструментами автоматизации сборки, становится необходимой зависимостью вашей программы).Такой подход не проще, чем сохранение внешнего файла данных (и в любом случае требует сохранения этих *.o
объектных файлов).
Таким образом, когда я открою его снова, все эти данные будутвсе еще сохраняться там
Если ваша цель - просто получить данные, если они были записаны в прошлом, просто храните данные в некоторой необязательной базе данных или файле (столько же программ, сколькоdo: ваш текстовый процессор попросит вас сохранить свой документ перед выходом, если вы запустите его без какого-либо документа и напишите в нем несколько слов) вне вашего исполняемого файла и напишите его перед выходом из программы.Не нужно перезаписывать ваш исполняемый файл!