Содержание
- Delphi: Почему я иногда получаю ошибку ввода-вывода 103 с этим кодом?
- 12 ответы
- Delphi IO Error 103
- Related Posts
- Delphi: почему я иногда получаю ошибку ввода-вывода 103 с этим кодом?
- 11 ответов
Delphi: Почему я иногда получаю ошибку ввода-вывода 103 с этим кодом?
В нескольких моих приложениях у меня есть код, подобный следующему:
В одном приложении, когда я впервые пытаюсь выполнить это, я постоянно получаю исключение I / O Error 103 в строке с оператором Append (файл существует до вызова этого). Однако все последующие попытки выполнить операцию будут работать нормально — до тех пор, пока я не перезапущу приложение.
Все документы, которые я нашел об этой ошибке до сих пор, указывали, что это может быть вызвано вызовом CloseFile без предварительного Reset or Rewrite ( Append обычно не упоминается) или если файл использовался другим процессом. Поскольку исключение происходит до вызова CloseFile очевидно, что это не могло быть первым.
Я уже пробовал вставить Reset сразу после AssignFile для хорошей меры, но тогда я получаю исключение в этой строке.
Также нет другого приложения, открыто обращающегося к этому файлу. Я говорю «открыто», потому что у меня есть небольшое подозрение, что антивирус (в моем случае TrendMicro) может быть причиной проблемы (так что, возможно, файл is в использовании). Если это действительно проблема, как лучше всего ее решить? Жесткое кодирование автоматической повторной попытки на самом деле не кажется мне простым решением .
Другой случай, когда я иногда получаю ошибку 103, — это код, который я использую для создания пустого файла (или, чаще, для очистки существующего файла):
В этом случае воспроизвести гораздо сложнее. Это случается намного реже. В большинстве случаев это происходит при первом запуске после того, как я перекомпилировал приложение. Неужели это снова мешает антивирус? Я видел это только на моей машине разработки и никогда не получал отчета от клиента. Как и в первом сценарии, это происходит только один раз за сеанс приложения (если вообще). Последующие попытки всегда успешны.
Есть ли предложения по другому, потенциально более надежному подходу к созданию пустых файлов или очистке существующих?
задан 11 марта ’09, 11:03
12 ответы
Я не вижу, что не так с автоматической повторной попыткой. Я не думаю, что ты можешь делать что-то еще. Если какой-то другой процесс читает файл, то ваше добавление / перезапись завершится ошибкой. А поскольку файл представляет собой журнал, есть большая вероятность, что что-то, например средство просмотра журнала или текстовый редактор, будем читать его в тот момент, когда вы пытаетесь его открыть.
Попробуйте открыть файл несколько раз с задержкой между попытками, прежде чем окончательно потерпите неудачу. Вы можете использовать экспоненциальную отсрочку, если хотите быть фантазией.
ответ дан 12 мар ’09, в 03:03
Хорошо, уже больше года с опозданием, но я собираюсь добавить свой комментарий к этому, поскольку он объясняет, почему это происходит.
У меня была точно такая же проблема в многопоточном приложении с кодом, почти идентичным приведенному выше фрагменту, и у меня были критические секции, защищающие код.
Проблема чаще всего возникала, когда одна операция регистрации быстро следовала за другой. Вторая операция не удалась бы по вышеуказанной причине.
Я думал, что это тоже антивирус, но ошибка произошла на одной машине, а не на другой, где на обоих был установлен Norton 360. На машине с проблемой была совершенно новая Windows 7, а на машине без нее — Windows XP. У коллеги также была проблема с запуском системы на виртуализированном компьютере с Windows Vista без установленной антивирусной программы.
Итак, мой вопрос был: «Почему эта машина с XP так отличалась от других?».
Во-первых, это не было девственницей, и, похоже, это ответ:
Были отключены оппортунистическая блокировка и кеширование NT. Большинство (зрелых) разработчиков Delphi знают, что при использовании BDE они отключены, чтобы поддерживать целостность файлов DBF и DB в многопользовательских ситуациях. Эти настройки не были отключены на новых машинах, потому что мы больше не разрабатываем файлы данных Paradox!
Кэширование с отложенной записью, похоже, оставляет блокировку чтения / записи для файла до тех пор, пока ОС не выполнит свою работу, что может произойти через несколько миллисекунд.
Итак, в моем случае второе событие журнала было заблокировано первым.
Хорошо, я не предлагаю вам отключить гибкую блокировку + кеширование NT. Одна из основных причин, по которой мы отошли от BDE, заключалась в том, чтобы не уговаривать клиентов возиться с такими настройками. Итак, есть четыре практических решения:
1) Чтобы повторить попытку в течение приемлемого периода времени, как указано в дангф.
2) открывать файл при загрузке приложения и держать его открытым в течение всего времени работы приложения. Не очень полезно, если вы запускаете несколько экземпляров приложения.
3) Лениво положите сон (1) перед кодом регистрации и надейтесь, что этого достаточно для снятия блокировки. Но это рискует замедлить работу вашей системы, если вы ведете много журналов.
или 4) Попробуйте . за исключением . завершите свой код. Но тогда вы, вероятно, гарантированно пропустите 100% вторых сообщений (в моем случае).
Источник
Delphi IO Error 103
Similarly to [this], the multithreading in a project has also caused the strange error, which is IO Error 103. It does not happen every time but randomly. I googled a bit and found this poston stackoverflow.
And I started to look into the Delphi code which has the File opening functions using Reset, AssignFile etc. Before, the following function will return the size of a given file.
The problem occurred most readily when one logging operation swiftly followed another. The second operation would fail for the above reason. To solve the IO 103 error, using the IO directive <$I->to suppress the exceptions and <$I+>to turn it on. The variable IOResult indicates that the IO operation is successful if it is zero. For example, the above code could be improved using the IOResult.
The function returns zero if there is an exception in reseting the file. If not, the IO Error 103 will be thrown out. Adding the IO code in the try … except … may suppress the 103 error. <$I+>is identical to <$IOCHECKS ON>and <$I->is the same as <$IOCHECKS OFF>.
If you have this 2343 installation/uninstallation problem that it seems not going away no matter…
If you have encounter the compiler problem [Unspecified Error] in Delphi 2007 on Windows 8…
This post gives a few C++ implementations that fill an array of integers by every…
By Default, the Delphi IDE stores the file information (version) directly in compiled Resource File…
In Delphi, the TFileStream can be used to stream the file reading and writing. Below…
I have raised a purchase order to purchase a license of Delphi XE8 and the…
If you want to get the file size in bytes for a file, you can…
Embarcadero has just released Delphi 10.1 Berlin on 20/April/2016. The CompilerVersion for Delphi 10.1 Berlin…
Tasks / Threads created by TParallel are more or less persistent which might be good…
Recently I am involved in optimising the Delphi code for I/O file access. I found…
Источник
Delphi: почему я иногда получаю ошибку ввода-вывода 103 с этим кодом?
в нескольких моих приложениях у меня есть код, подобный следующему:
в одном приложении при первой попытке выполнить это я последовательно получаю исключение 103 ошибки ввода-вывода в строке с инструкцией Append (файл существует до вызова этого). Однако все последующие попытки операции будут работать нормально-до тех пор, пока я не перезапущу приложение.
все документы, которые я нашел об этой ошибке, до сих пор указывали, что это будет вызвано вызовом CloseFile без предварительного Reset или Rewrite ( Append обычно не упоминается) или если файл используется другим процессом. Поскольку исключение возникает перед вызовом CloseFile это, очевидно, не может быть бывшим.
Я уже пытался вставить Reset сразу после AssignFile для хорошей меры, но затем я получаю исключение в этой строке.
также нет другого приложения, открыто доступ к этому файлу. Я говорю «открыто», потому что у меня есть небольшое подозрение, что антивирус (TrendMicro в моем случае) может быть cuplrit здесь (так что, возможно, файл is В использовать). Если это действительно проблема, то как лучше ее обойти? Жесткое кодирование автоматической повторной попытки на самом деле не кажется мне чистым решением.
другим случаем, когда я иногда получаю ошибку 103, является этот код, который я использую для создания пустого файла (или чаще для пустого существующего файла):
в этом случае гораздо труднее воспроизводить. Это случается гораздо реже. В большинстве случаев это происходит при первом запуске после перекомпиляции приложения. Может, это опять антивирус мешает? Я только когда-либо видел, как это происходит на моей машине разработки и никогда не получал отчета от клиента. Как и в первом сценарии, это происходит только один раз за сеанс приложения (если вообще). Последующие попытки всегда успешны.
любые предложения для другого, потенциально более отказоустойчивый подход к созданию пустых файлов или опорожнению существующих?
11 ответов
Я не вижу, что не так с автоматической повторной попыткой. Я не вижу, что ты можешь сделать что-то еще. Если какой-то другой процесс читает файл, то ваше добавление/перезапись завершится ошибкой. И поскольку файл является журналом, есть хороший шанс, что что-то, например, средство просмотра журнала или текстовый редактор,будет читать его в тот момент, когда вы пытаетесь открыть его.
попробуйте открыть файл несколько раз с задержкой между попытками, прежде чем окончательно потерпеть неудачу. Вы можете использовать экспоненциальный отступи, если хочешь быть модным.
хорошо, это более чем на год позже, но я собираюсь добавить свой комментарий к этому, так как это объясняет, почему это происходит.
У меня была точно такая же проблема в многопоточном приложении с кодом, почти идентичным приведенному выше фрагменту, и у меня были критические разделы, защищающие код.
проблема возникла наиболее легко, когда одна операция регистрации быстро последовала за другой. Вторая операция провалится по вышеуказанной причине.
Я думал, что это антивирус программное обеспечение тоже, но ошибка произошла на одной машине, а не на другой, где оба были установлены Norton 360. Машина с проблемой была совершенно новой Windows 7, а без нее была Windows XP. У коллеги также была проблема с запуском системы под виртуализированной машиной Windows Vista без установленной проверки на вирусы.
Итак, мой вопрос был: «почему эта машина XP так отличается?».
во-первых, он не был девственником, и это ответ, кажется:
оппортунистическая блокировка и кэширование NT были отключены. Большинство (зрелых) разработчиков Delphi будут знать, что при использовании BDE они отключены для поддержания целостности файлов DBF и DB в многопользовательских ситуациях. Эти настройки не были отключены на новых машинах, потому что мы больше не разрабатываем файлы данных Paradox!
кэширование с задержкой записи, похоже, оставляет блокировку чтения / записи в файле до тех пор, пока ОС не сделает свое дело, что может составлять несколько миллисекунд позже.
Итак,в моем случае второе событие журнала было заблокировано первым.
хорошо, я не предлагаю Вам отключить оппортунистическую блокировку + кэширование NT. Одна из основных причин, по которой мы отошли от BDE, заключалась в том, чтобы не убеждать клиентов возиться с такими настройками. Итак, есть четыре практических решения:
1) повторить попытку в течение приемлемого периода времени, как указано dangph.
2) Открыть файл, когда приложение загружается и держит его открытым в течение всего срока действия приложения. Не так полезно, если вы используете несколько экземпляров приложения.
3) лениво положите сон (1) перед кодом регистрации и надейтесь, что этого достаточно для разблокировки замка. Но это рискует замедлить вашу систему, если вы делаете много журналов.
или 4) Попробуйте. кроме..конец вокруг вашего кода. Но тогда вы, вероятно, гарантированно пропустите 100% вторых сообщений (ссылаясь на мой случай.)
помимо антивируса, это также может быть программное обеспечение для индексирования или управления файлами, например Google Desktop. Однако реальная проблема здесь заключается в том, что сообщение об ошибке не поможет вам решить проблему. Я предлагаю вам переписать код для использования TFileStream вместо этого, чтобы улучшить ваши сообщения об ошибках.
как правило, вы должны положить открытие файла перед попыткой попробовать..наконец:—3—>
(попробуйте, наконец, не имеет никакого смысла в последнем случае)
в противном случае закрытие файла может завершиться неудачей, потому что он не может быть открыт, и это замаскирует реальную ошибку.
но я не думаю, что здесь проблема.
является ли ваше приложение многопоточным? У меня когда-то была такая же проблема, когда код ведения журнала вызывался одновременно из обоих потоков. Если это так, используйте TCriticalSection для управления доступом.
не могли бы вы посмотреть на случайную ошибку от чего — то еще, скомпилированного в $I-состоянии?
ваш пример кода должен работать в целом, эти ошибки кажутся ошибками доступа. Чтобы обнаружить это, вы можете попытаться отключить TrendMicro и посмотреть, сохраняется ли проблема.
Если я понимаю это correctliy, ваше назначение файла не выполняется. Вы уверены, что FileChecks на вызове AssignFile? Это довольно необычно, но вы можете проверить это, используя:
Я согласен использовать tfilestream (или что угодно, кроме функции доступа к файлам низкого уровня). Это критично для производительности и может быть огромной проблемой при переходе на Unicode.
Я ненавижу Windows. смотрите почему:
это код, который решает проблему перезаписи (без сообщения):
Я отлаживаю эту проблему, ставя много ShowMessage. имел немного воображения после попытки не абсурдных вещей (файл был ранее oppened и т. д.). что произойдет, если я попробую переписать дважды? Сюрприз. если первое терпит неудачу, то вторая попытка работает!
Я знаю, что это абсурд, но это работает!
Я знал это, потому что я помещал много сообщений, просто так:
и я получил эти два сообщения:
- 1,2,3,4, когда fisrt переписать работает
- 1,2,3,5,6 когда fisrt переписать не удается, обратите внимание, есть 6, так что второй переписать работал
надеюсь, это поможет другим не так злиться.
Д. П.: такая же проблема происходит сброс. теперь я всегда инкапсулирую их в такую попытку. кроме блока и избавиться от проблемы!
путь Здравствуйте. Вероятно, уже слишком поздно отвечать на исходный вопрос, но я хочу добавить свою часть, и, несмотря на то, что это не прямой ответ на исходный вопрос, я хочу внести свой вклад, поскольку я думаю, что это может помочь некоторым другим в поисках такого ответа.
Я получил тот же ответ на ошибку, но в совершенно другом программном обеспечении, в частности, EIS analyser, больше раз я пытался открыть файл, но некоторое время он мог быть открыт. Это было любопытно для меня, поэтому я схватил для интернета. И действительно, как казалось невероятным (потому что средняя программа довольно мала), я нашел такой вызов ошибки. Я снимал кожу с вышеуказанных ответов и тот, который имеет две проверки с зеленым галочкой, я следовал, просто интуитивно, и это так: Когда я открыл файл в другой программе, он не позволит мне открыть его как файл в анализаторе EIS.
Итак, общий вывод: если вы открыли файл в одной программе, он не позволит вам открыть его в любом другом месте, и вы получите ошибку ввода-вывода 103.
PS: немного смелый и слабый и легкий вывод (без правильного чтения(но не успел, извините) вышеуказанные ответы), но я надеюсь, что у вас есть смысл. 🙂 Овации.
Источник
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
program lab14; uses crt,utils; var a1,a2,a3:text; action:char; vidnosh: array[1..4,1..4] of integer; way:string; open:boolean; name,output: string; procedure interface1(var action:char; open:boolean); begin if open=false then begin writeln('Âûáåðèòå îïåðàöèþ:'); writeln('"1" - Ñãåíåðèðîâàòü îòíîøåíèå'); writeln('"0" - Âèõîä èç ïðîãðàììû'); readln(action); while not (action in ['1','0']) do begin writeln('Íåâåðíûé êîä îïåðàöèè ïîâòîðèòå ââîä.'); readln(action); end; end else begin writeln('Âûáåðèòå îïåðàöèþ:'); writeln('"1" - ñãåíåðèðîâàòü îòíîøåíèå'); writeln('"2" - Ïðîñìîòð èìåí ôàéëîâ â êîòîðûõ åñòü çàïèñàíûå îòíîøåíèÿ'); writeln('"3" - Ïðîñìîòð èìåí ôàéëîâ â êîòîðûõ åñòü çàïèñàíûå ðåçóëüòàòû'); writeln('"4" - Çàïèñàòü îòíîøåíèå â ôàéë'); writeln('"5" - ïîñ÷èòàòü îáðàòíîå îòíîøåíèå'); writeln('"0" - âûõîä èç ïðîãðàììû'); read(action); while not (action in ['1','2','3','4','5','0']) do begin writeln('Íåâåðíûé êîä îïåðàöèè ïîâòîðèòå ââîä.'); readln(action); end; end; end; procedure out_put(vidnosh: array[1..4,1..4] of integer); var i,j:integer; begin clrscr; writeln('R ',' 1 ','2 ','3 ','4'); for i:=1 to 4 do begin write(i); for j:=1 to 4 do write(' ',vidnosh[i,j]); writeln; writeln; end; end; procedure generate(var vidnosh: array[1..4,1..4] of integer; var open:boolean); var i,j: integer; name:string; begin open:=true; clrscr; randomize; for i:=1 to 4 do begin for j:=1 to 4 do vidnosh[i,j]:=random(2); end; out_put(vidnosh); end; procedure writing(vidnish: array[1..4,1..4] of integer;name:string;var a1:text;way:string); var i,j:byte; begin clrscr; writeln('Ââåäèòå èìÿ ôàéëà:'); read(name); ChDir(way); assign(a1, name); rewrite(a1); writeln(a1,'R ',' 1 ','2 ','3 ','4'); for i:=1 to 4 do begin write(a1,i); for j:=1 to 4 do write(a1,' ',vidnosh[i,j]); writeln; writeln; end; writeln('Îòíîøåíèå áûëî ñîõðàíåíî.'); close(a1); end; procedure search(way:string;var output:string;var a3:text); var list: array[1..100] of string; num1,num2,i,j:integer; sr: SearchRec; open:boolean; begin clrscr; num1:=0; ChDir(way); if FindFirstFile('*.*', sr) then begin inc(num1); writeln('Ôàéëû êîòîðûå áûëè íàéäåíû:'); writeln(' ¹ | Íàçâàíèå ôàéëà'); write(num1:3, ' | ', sr.Name); writeln; list[num1]:=sr.Name; while FindNext(sr) do begin inc(num1); write(num1:3, ' | ', sr.Name); writeln; list[num1]:=sr.Name; end; end; if num1 = 0 then writeln('Íè îäíè ôàéë íå áûë íàéäåí') else begin FindClose(sr); writeln('Âûáåðèòå íîìåð ôàéëà äëÿ îòêðûòèÿ'); readln(num2); while (num2 <= 0) or (num2 > num1) do begin writeln('Îøèáêà,ïîïðîáóéòå åùå ðàç'); readln(num2); end; begin assign(a3, list[num2]); reset(a3); open:=true; writeln; clrscr; TextBold; writeln('Ôàéë áûë îòêðûò'); TextNormal; while not eof(a3) do begin readln(a3, output); writeln(output); end; end; end; end; procedure obratn(vidnosh:array[1..4,1..4] of integer; name:string; var a2:text;way:string); var i,j:integer; x:char; m:array[1..4,1..4] of integer; begin clrscr; for i:=1 to 4 do for j:=1 to 4 do m[j,i]:=vidnosh[i,j]; writeln('Îáðàòíàÿ ìàòðèöà èìååò âèä:'); for i:=1 to 4 do begin for j:=1 to 4 do write(m[i,j]:3); writeln; end; writeln('Çàïèñàòü ðåçóëüòàò â ôàéë?(Y/N)>'); read(x); if (x='y') or (x='Y') then begin writeln('Ââåäèòå èìÿ ôàéëà:'); read(name); ChDir(way); assign(a2, name); rewrite(a2); writeln(a2,'R ',' 1 ','2 ','3 ','4'); for i:=1 to 4 do begin write(a2,i); for j:=1 to 4 do write(a2,' ',vidnosh[i,j]); writeln; writeln; write(a2,'Îáðàòíàÿ ìàòðèöà:'); for i:=1 to 4 do begin for j:=1 to 4 do write(a2,m[i,j]:3); close(a2); end; end; end; end; begin open:=false; repeat clrscr; interface1(action, open); case action of '1': generate(vidnosh, open); '2': begin way:='E:vidn'; search(way,output,a3); end; '3': begin way:='E:result'; search(way,output,a3); end; '4': begin way:='E:vidn'; writing(vidnosh,name,a1,way); end; '5': begin out_put(vidnosh); way:='E:result'; obratn(vidnosh,name,a2,way); end; end; if action<>'0' then begin writeln('Íàòèñí³òü ENTER'); readln; end; if (action='2') or (action='3') then close(a3); until action='0'; end. |
Okay, it’s over a year late, but I’m going to add my comment to this, as it explains why this is happening.
I had the exact same problem in a multi-threaded application with code almost identical to the snippet above and I had critical sections protecting the code.
The problem occurred most readily when one logging operation swiftly followed another. The second operation would fail for the above reason.
I thought it was anti-virus software too, but the error happened on one machine and not the other, where both had Norton 360 installed. The machine with the problem was brand new Windows 7 and the one without was Windows XP. A colleague also had the problem running the system under a virtualised Windows Vista machine with no virus checker installed.
So my question was, «why was this XP machine so different?».
For one, it wasn’t virgin, and that is the answer it seems:
Opportunistic locking and NT caching were turned off. Most (mature) Delphi developers will know that when using BDE, these are turned off in order to maintain DBF and DB file integrity in multi-user situations. These settings were not disabled on the newer machines because we no longer develop for Paradox data files!
Delayed write caching seems to leave a read/write lock on the file until the OS has done its business, which could be several milliseconds later.
So, in my case, the second log event was being blocked by the first.
Okay, I’m not suggesting that you turn off opportunistic locking + NT Caching. One of the major reasons we moved away from BDE was to avoid persuading customers to tinker with such settings. So, there are four practical solutions:
1) To retry for an acceptable period of time, as mentioned by dangph.
2) to open the file when the application loads and hold it open for the full duration of the application. Not so useful if you are running multiple instances of the application.
3) Lazily put a sleep(1) before the logging code and hope that is long enough for the lock to be released. But that risks slowing your system down if you are doing lots of logging.
or 4) Put a try…except..end around your code. But then you are probably guaranteed to miss 100% of the second messages (referring to my case).
Okay, it’s over a year late, but I’m going to add my comment to this, as it explains why this is happening.
I had the exact same problem in a multi-threaded application with code almost identical to the snippet above and I had critical sections protecting the code.
The problem occurred most readily when one logging operation swiftly followed another. The second operation would fail for the above reason.
I thought it was anti-virus software too, but the error happened on one machine and not the other, where both had Norton 360 installed. The machine with the problem was brand new Windows 7 and the one without was Windows XP. A colleague also had the problem running the system under a virtualised Windows Vista machine with no virus checker installed.
So my question was, «why was this XP machine so different?».
For one, it wasn’t virgin, and that is the answer it seems:
Opportunistic locking and NT caching were turned off. Most (mature) Delphi developers will know that when using BDE, these are turned off in order to maintain DBF and DB file integrity in multi-user situations. These settings were not disabled on the newer machines because we no longer develop for Paradox data files!
Delayed write caching seems to leave a read/write lock on the file until the OS has done its business, which could be several milliseconds later.
So, in my case, the second log event was being blocked by the first.
Okay, I’m not suggesting that you turn off opportunistic locking + NT Caching. One of the major reasons we moved away from BDE was to avoid persuading customers to tinker with such settings. So, there are four practical solutions:
1) To retry for an acceptable period of time, as mentioned by dangph.
2) to open the file when the application loads and hold it open for the full duration of the application. Not so useful if you are running multiple instances of the application.
3) Lazily put a sleep(1) before the logging code and hope that is long enough for the lock to be released. But that risks slowing your system down if you are doing lots of logging.
or 4) Put a try…except..end around your code. But then you are probably guaranteed to miss 100% of the second messages (referring to my case).
Почему выскакивает ошибка при обработке файла: IO error 103 ?
var
fall, f1: TextFile;
S: string;
begin
AssignFile(fall, OpenDialog1.FileName);
reset(fall);
if CheckBox1.Checked then
begin
AssignFile(f1, 'Organization.txt');
rewrite(f1);
end;
//работаем по строкам в файле
while not Eof(fall) do
begin
//читаем строку
ReadLn(fall, S);
if CheckBox1.Checked and (Pos(AnsiLowerCase(Edit1.Text), AnsiLowerCase(s)) > 0) then
writeln(f1, S);
end;
CloseFile(fall);
CloseFile(f1); // <<-- Ошибка выскакивает тут
end;
![]()
Kromster
13.2k12 золотых знаков41 серебряный знак70 бронзовых знаков
задан 24 фев 2018 в 17:51
![]()
0
Ошибка, с большой долей вероятности, случается потому, что файлы вы открываете на чтение/запись по условию, а вот закрываете файл затем уже в любом случае. Скорее всего, одно из условий:
if CheckBox1.Checked then
if CheckBox2.Checked then
if CheckBox3.Checked then
у вас не выполняется, но при этом CloseFile вы делаете для всех файлов без условий. Исправьте это, введя те же самые условия и для CloseFile.
![]()
Kromster
13.2k12 золотых знаков41 серебряный знак70 бронзовых знаков
ответ дан 24 фев 2018 в 18:06
![]()
Viktor TomilovViktor Tomilov
7,9774 золотых знака22 серебряных знака60 бронзовых знаков
3
if CheckBox1.Checked then
CloseFile(f1);
ответ дан 24 фев 2018 в 18:07
1
В нескольких моих приложениях у меня есть код, похожий на следующий:
if ForceDirectories(ExtractFilePath(lLogName)) then
begin
AssignFile(lLog, lLogName);
try
if FileExists(lLogName) then
Append(lLog)
else
Rewrite(lLog);
Writeln(lLog, lLogLine);
finally
{$I-}CloseFile(lLog);{$I+}
end;
end;
В одном приложении, в первый раз, когда я пытаюсь выполнить это, я последовательно получаю исключение 103 ошибки ввода-вывода в строке с оператором Append (файл существует до вызова этого). Все последующие попытки операции будут работать нормально — пока я не перезапущу приложение.
Все документы, которые я нашел об этой ошибке, указали, что это вызвано вызовом CloseFile без предшествующих Reset или Rewrite (Append обычно не упоминается) или если файл находился в использование другим процессом. Поскольку исключение происходит до вызова CloseFile, оно, очевидно, не может быть первым.
Я уже пробовал вставить Reset сразу после AssignFile для хорошей меры, но затем я получаю исключение в этой строке.
Также нет другого приложения, открыто доступного для этого файла. Я говорю «открыто», потому что у меня есть небольшое подозрение, что антивирус (TrendMicro в моем случае) может быть куклитом здесь (так что, возможно, используется файл ). Если это действительно проблема, что было бы лучше всего вокруг нее? Жесткое кодирование автоматической повторной попытки на самом деле не похоже на чистое решение для меня…
Другим случаем, когда я иногда получаю ошибку 103, является этот код, который я использую для создания пустого файла (или чаще всего для удаления существующего файла):
AssignFile(lFile, AFileName);
try
Rewrite(lFile);
finally
CloseFile(lFile);
end;
В этом случае это намного сложнее воспроизвести. Это происходит гораздо реже. В большинстве случаев это похоже на первый запуск после того, как я перекомпилировал приложение. Может ли это снова стать антивирусом? Я только когда-либо видел это на моей машине разработки и никогда не получал отчет от клиента. Как и в случае с первым сценарием, это всегда случается один раз на один сеанс приложения (если вообще). Последующие попытки всегда успешны.
Любые предложения по другому, потенциально более безопасному подходу к созданию пустых файлов или опорожнению существующих?
Ответ 1
Я не вижу, что не так с автоматической попыткой. Я не вижу, что ты можешь сделать что-нибудь еще. Если какой-либо другой процесс читает файл, то ваш Append/Rewrite завершится с ошибкой. И поскольку файл является журналом, есть хорошая вероятность, что что-то, например, просмотрщик журналов или текстовый редактор, будет читать его в тот момент, когда вы попытаетесь его открыть.
Попробуйте открыть файл несколько раз с задержкой между попытками до окончательного завершения. Вы можете использовать экспоненциальный откат, если хотите, чтобы вы были фантазии.
Ответ 2
Хорошо, это на год, но я собираюсь добавить свой комментарий к этому, потому что это объясняет, почему это происходит.
У меня была такая же проблема в многопоточном приложении с кодом, почти идентичным фрагменту выше, и у меня были критические разделы, защищающие код.
Проблема произошла наиболее легко, когда одна операция регистрации быстро последовала за другой. Вторая операция потерпит неудачу по вышеуказанной причине.
Я думал, что это тоже антивирусное программное обеспечение, но ошибка произошла на одном компьютере, а не на другом, где оба были установлены Norton 360. Машина с проблемой была совершенно новая Windows 7, а одна без Windows XP. У коллеги также возникла проблема с запуском системы под виртуализированной машиной Windows Vista без установленного антивируса.
Итак, мой вопрос: «Почему эта машина XP была такой разной?».
Во-первых, он не был девственником, и это ответ кажется:
Оппортунистическая блокировка и кэширование NT были отключены. Большинство (зрелых) разработчиков Delphi будут знать, что при использовании BDE они отключены, чтобы поддерживать целостность файлов DBF и DB в многопользовательских ситуациях. Эти настройки не были отключены на новых машинах, потому что мы больше не разрабатываем файлы данных Paradox!
Отложенное кэширование записи, похоже, оставляет блокировку чтения/записи в файле до тех пор, пока ОС не выполнит свою работу, и это может быть несколько миллисекунд позже.
Итак, в моем случае второе событие журнала блокировалось первым.
Хорошо, я не предлагаю отключить оппортунистическую блокировку + NT Caching. Одна из основных причин, по которым мы отошли от BDE, заключалась в том, чтобы избежать убеждения клиентов возиться с такими настройками. Итак, есть четыре практических решения:
1) Повторить попытку в течение приемлемого периода времени, как указано dangph.
2), чтобы открыть файл, когда приложение загружается и удерживает его открытым в течение всего срока действия приложения. Не очень полезно, если вы используете несколько экземпляров приложения.
3) Летите положить спать (1) перед кодом регистрации и надеяться, что это достаточно долго, чтобы блокировка была выпущена. Но это может замедлить работу вашей системы, если вы делаете много протоколирования.
или 4) Положите попытку… кроме.. вокруг вашего кода. Но тогда вам, вероятно, гарантированно пропустите 100% вторых сообщений (со ссылкой на мой случай).
Ответ 3
Помимо антивируса, он также может быть индексирующим программное обеспечение или программное обеспечение для управления файлами, например, Google Desktop. Однако настоящая проблема заключается в том, что сообщение об ошибке не поможет вам решить проблему. Я предлагаю вам переписать код для использования TFileStream, вместо этого, чтобы улучшить ваши сообщения об ошибках.
Ответ 4
Обычно вы должны открыть файл перед попыткой try..finally:
if fileexists then
append(..)
else
rewrite(..);
try
// do something with the file
finally
CloseFile(..);
end;
и
AssignFile(lFile, AFileName);
Rewrite(lFile);
CloseFile(lFile);
(попробуйте, наконец, не имеет никакого смысла в последнем случае)
В противном случае закрытие файла может завершиться неудачно, потому что оно не может быть открыто, и это замаскирует реальную ошибку.
Но я не думаю, что это проблема.
Ответ 5
Является ли ваше приложение многопоточным? У меня когда-то была такая же проблема, как и при одновременном вызове кода регистрации из обоих потоков. Если это так, используйте TCriticalSection для контроля доступа.
Ответ 6
Не могли бы вы взглянуть на блуждающую ошибку из чего-то еще, скомпилированного в состоянии $I?
Ответ 7
Ваш примерный код должен работать вообще, эти ошибки, похоже, являются ошибками доступа. Чтобы обнаружить случай этого, вы можете попытаться отключить TrendMicro и посмотреть, не исчезла ли проблема.
Ответ 8
Если я правильно понимаю, ваше назначение файла не выполняется. Вы уверены, что FileChecks находятся во время вызова AssignFile? Это довольно необычно, но вы можете проверить это, используя:
{$IFOPT I-}
if IOResult <> 0 then
begin
// Error handling
end;
{$ENDIF}
Я соглашаюсь использовать TFileStream (или что-то вроде функции доступа к низкоуровневому файлу). Это критично для производительности и может стать огромной проблемой при переходе на Unicode.
Ответ 9
Я ненавижу Windows… вижу, почему:
Это код, который решает проблему ReWrite (без сообщений):
AssignFile(MyFileHandler,RouteToWritableExistantFile);
try
ReWrite(MyFileHandler); // This sometimes fails
except
ReWrite(MyFileHandler); // When prior fails, this runs OK
end;
Да, это абсурдно… если ReWrite терпит неудачу, сделайте Rewrite… но он работает для меня в 100% случаев.
Я ДЕБЮГ, что проблема, связанная с большим количеством ShowMessage… была немного фантазии после попытки не абсурдных вещей (файл был ранее открыт и т.д.)… что произойдет, если я попробую ReWrite дважды? Сюрприз… если первый провал, вторая попытка срабатывает!
Я знаю, что это абсурд, но он работает!
Я знал это, потому что я писал много сообщений, например:
ShowMessage('1: - pre - AssignFile - ');
AssignFile(MyFileHandler,RouteToWritableExistantFile);
ShowMessage('2: - post - AssignFile - ');
try
ShowMessage('3: - pre - ReWrite - ');
ReWrite(MyFileHandler); // This sometimes fails
ShowMessage('4: - pre - ReWrite - ');
except
ShowMessage('5: - pre - ReWrite - ');
ReWrite(MyFileHandler); // When prior fails, this allways runs OK (it is absurd, but works)
ShowMessage('6: - pre - ReWrite - ');
end;
И я получил две сообщения:
- 1,2,3,4 при работе fisrt rewrite
- 1,2,3,5,6, когда переписывание fisrt не выполняется, обратите внимание, что существует 6, поэтому вторая перезапись работала
Надеюсь, что это поможет другим, не настолько безумным!!!
P.D.: Такая же проблема возникает с Reset… теперь я всегда инкапсулирую их в такую попытку… кроме блока и избавлюсь от проблемы!
Ответ 10
Привет. Возможно, слишком поздно для ответа на исходный вопрос, но я хочу добавить свою часть, и, несмотря на то, что это не прямой ответ на исходный вопрос, я хочу внести свой вклад, поскольку я думаю, что это может помочь некоторым другим, кто ищет такой вид ответа.
У меня получился такой же ответ на ошибку, но в полнофункциональном программном обеспечении, в частности, анализаторе EIS, больше раз я пытался открыть файл, но через некоторое время его можно было открыть. Мне это было любопытно, поэтому я схватился за интернет. И действительно, как маловероятно, казалось (потому что значимая программа довольно мала), я нашел такой вызов ошибки. Я снимал эти ответы, и тот, у которого есть две проверки с зеленым чеком, я сразу последовал, просто интуитивно, и это так: Когда я открыл файл в другой программе, он не позволит мне перейти к откройте его как файл в анализаторе EIS.
Итак, общий вывод: когда вы открыли файл в одной программе, он не позволит вам открывать его где-нибудь еще, и вы получите сообщение об ошибке ввода/вывода ошибки 103.
PS: Немного смелый и лёгкий и легкий вывод (без правильного чтения (но у меня нет времени, извините) вышеупомянутые ответы), но я надеюсь, что у вас есть точка.:) Приветствия.
Ответ 11
Я случайно сделал CloseFile дважды и имел эту ошибку.