Другие языки программирования и технологии

Delphi, работа с файлами

Моя проблема такова: при попытке открыть текстовый файл при помощи команды Rewrite, и если он (файл) существует по указанному в AssignFile пути, то происходит исключение "File access denied".
Как исправить ?
При этом файл нигде больше не открыт, что я знаю абсолютно точно.
P.S. Если файла не существует, то команда Rewrite нормально его (файл) создаёт и открывает.
1. Вы используете методы доступа к файлам, которые устарели лет на 15-20, сегодня они используются исключительно в целях обучения.

2. Ошибка, соответствующая строке "File access denied", не документирована. Для Rewrite может быть: запрет создать файл в указанном месте (недостаток прав) , файл уже существует и кем-то открыт. Читайте подробнее описание ошибок функции CreateFile в MSDN, именно она вызывается в конце концов, и именно её ошибки возвращаются

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

Теоретически можно преобразовать переменную типа файл в структуру TFileRec, подменить Handle на созданный с помощью FileOpen с правильными параметрами совместного доступа, а потом использовать стандартные Pascal-style функции, но зачем? Для низкоуровневого доступа к файлам с совместным доступом используйте FileRead, FileWrite с FileSeek, или на худой конец - TFileStream. Такие файлы очень редко бывают текстовыми.
Сергій Кропивницький
Сергій Кропивницький
11 112
Лучший ответ
Олег Маматов Я может и похож на до###ёба (устаревшего прогрОммиста) , но не считаю себя уж совсем тупым.

"... одновременную запись и чтение реализовать практически нереально с помощью таких функций ..."
В этом выражении ключевое слово "практически". Кто сказал, что запись/чтение будет происходить в БУКВАЛЬНОМ смысле одновременно? Даже "многозадачное" ядро процессора не является многозадачным, как таковым, а лишь выполняет очередь операций с учётом приоритета по времени, и делает это оЧень быстро.
Олег Маматов Почему слово ключевое? Объясню суть происходящего в моей программе: есть одна функция для чтения из одного файла, и эта функция вызывается из разных мест моей программы; вызовы могут происходить как последовательно (в разное время) , так и "параллельно" (одновременно).
Олег Маматов В любом случае в функции команда открытия файла вписана в блок try (попытаться) ; если произойдёт ошибка
(которую команда try отловит на команду except, без описания ошибки) , то логическая переменная примет значение ЛОЖЬ (сразу после строки except), и по этой логической переменной произойдёт переход в начало цикла с постусловием (repeat находится перед try). И так до тех пор, пока кто то, кто вызвал функцию записи в файл, не закроет файл - будет выполняться этот цикл. Таким образом я реализовал ту самую "параллельность" записи. "Очередь задач" не напоминает ?
Олег Маматов Что же касается возможности отсутствия файла, как такового, то перед вызовом функции чтения (да, такая тоже есть) проверяется наличие файла, и если он существует, то только тогда произойдёт вызов функции (чтения) .

Как я решил свою проблему, о которой написал в вопросе: опять же try, в случае исключения файл будет удалён, и после чего всё равно выполнится команда Rewrite(); ведь эта команда по идее должна создать новый файл? А я писал (опять же, в вопросе) , что если файла не существует - то команда Rewrite выполняется удачно.
Олег Маматов Зачем мне всё это? Всё очень просто: программа во время запуска проверяет, существует ли указанный файл, и если существует, то вызывается функция чтения, и содержимое файла сохраняется в глобальную переменную. Во время выполнения программы к глобальной переменной дополняется то, что необходимо записать, после вызова Rewrite просто напросто записывается содержимое этой глобальной переменной.
Всё через жопу (а кто сказал, что будет легко ?), но работает.
Олег Маматов Ну и да: ручное редактирование содержимого текстового файла во время выполнения программы не предполагается; даже если туда (в файл) что то кто то добавил, и этот кто то не является моей программой - это что то будет удалено вместе с файлом, и произойдёт запись того, что хранится в глобальной переменной.

Ну и в примечание:
"... сегодня они используются исключительно в целях обучения ...". По этому поводу скажу вот что: я пишу курсовую работу, и мне плевать на эти ваши "новые методы" доступа к фалам.
Команда Rewrite в Delphi для работы с текстовыми файлами не используется. Используй TStringList.
Андрей Чикалов
Андрей Чикалов
97 561
Проверь из-под отладчика, что имя файла - правильное.
Проверь, что все ок с правами доступа, особенно если файл лежит в папке с программой: попробуй создавать его в моих документах или папке временных файлов.
Проверь, что файл действительно не открыт: в момент ошибки попытайся создать, удалить, скопировать фай любым файл-менеджером типа фара.
Попробуй погуглить код ошибки, который скажет Дельфи, по нему будет видно, что не так с файлом. Если 103 - то файл точно забыли закрыть.
Убедись, что файл не открыт (не залочен) вирусом (антивирусом) .

И таки да, я бы советовал держать содержимое файла в памяти, в том же TSTringList и время от времени тупо сбрасывать его на диск. Если, конечно, файл меньше двух гигов.
Олег Маматов Я держу содержимое файла в в обычном string'е, и при возникновении какого то из прописанных в коде событий происходит сброс данных на диск.
Резет ();
Но лучше использовать потоки.
Олег Маматов В моём случае программа будет пытаться читать и писать в файл из нескольких мест, иногда одновременно, поэтому с потоком будет тяжело.
Но как я сказал, Rewrite генерит denied даже тогда, когда нет параллельного доступа.

Ну и да, вытяжка из интернет-справочника:

Если файл не существует, то он будет создан.
Если файл уже существует, содержание будет потеряно, и новые данные добавятся в начало.

http://www.delphibasics.ru/ReWrite.php

Второй пункт не выполнен