Страница 1 из 1

Access denied при частом открытии файла

СообщениеДобавлено: 03.11.2008 17:40:50
voltron
Есть у нас в конторе программа (написанная не мной), которая читает текстовые файлы определенного формата, извлекает из них информацию, и после форматирования пишет ее в результирующий файл. Вот фрагмент кода:
Код: Выделить всё
// просматриваем исходные файлы
for i:=0 to lstFiles.Lines.Count - 1 do
begin
  //сначала считывается и обрабатывается исх. файл
  lstSource.LoadFromFile(lstFiles.Lines[i]);
  ...

  //результат обработки пишем в результирующий файл
  AssignFile(OutFile, OutFileName);
  try
    Append(OutFile);
   
    //запись информации
    write(OutFile, CadNom + SEPARATOR);
    write(OutFile, Owner + SEPARATOR);
    ...
    writeln(OutFile, ActRegDate); //формируем переход на след. строку
    CloseFile(OutFile);
  except
    on E:EInOutError do
      DebugLn('Error: ' + E.Message);
  end;
end;

При большом количестве исходных файлов (4000 и больше), ближе к концу списка начинает возникать ошибка "Access denied" на строке Append(OutFile). Файл-результат больше нигде не используется, после записи каждой порции данных закрывается. Пробовал вынести открытие и закрытие результирующего файла за пределы цикла (чтобы не открывать файл при записи новой порции данных) - не помогло.
В чем может быть проблема и как лучше организовать процесс записи (пишутся строки разной длины)?

Re: Access denied при частом открытии файла

СообщениеДобавлено: 03.11.2008 17:49:16
FedeX
Попробуй использовать функцию Flush перед записью следующей порции. (я ей не пользовался, но вроде есть такая).
Попробуй писать всё в одну строку (конкатенировать или, если возможно, сразу выделить необходимый обьём), и только в конце писать всю строку в бинарный файл.

Re: Access denied при частом открытии файла

СообщениеДобавлено: 03.11.2008 18:14:13
Vadim
voltron
Попробуйте вообще использовать класс TStringList. У него есть метод SaveToFile(), при этом он сразу выкидывает в файл весь свой набор строк:
Код: Выделить всё
Var
  st: TStringList;
Begin
st:=TStringList.Create;
// просматриваем исходные файлы
for i:=0 to lstFiles.Lines.Count - 1 do
begin
  //сначала считывается и обрабатывается исх. файл
  lstSource.LoadFromFile(lstFiles.Lines[i]);
  ...

  //результат обработки пишем в StringList
   
    //запись информации
    st.Add(CadNom + SEPARATOR + Owner + SEPARATOR+...);
    ...
End;
st.SaveToFile(OutFileName);
st.Free;

Съэкономит кучу времени, т.к. выходной файл открывается всего один раз.

Re: Access denied при частом открытии файла

СообщениеДобавлено: 03.11.2008 18:44:26
voltron
FedeX писал(а):Попробуй использовать функцию Flush перед записью следующей порции. (я ей не пользовался, но вроде есть такая).

Есть такая процедура, она выполняет принудительную запись изменений (сбрасывает файловый буфер на диск). Данные нормально пишутся и без нее, проблема возникает при попытке открыть файл на дозапись, т.е. Flush здесь не причем.
Vadim писал(а):Попробуйте вообще использовать класс TStringList

Именно так и собираюсь поступить. Просто интересует причина появления таких ошибок. Нашел на Королевстве Дельфи похожую проблему http://www.delphikingdom.com/asp/answer.asp?IDAnswer=50614

Re: Access denied при частом открытии файла

СообщениеДобавлено: 03.11.2008 19:18:26
Vadim
voltron писал(а):Просто интересует причина появления таких ошибок.

Точно сказать не могу, т.к. ни разу с таким не сталкивался, но, возможно, причина в кэшировании. Файл при следующей итерации, пытается открываться раньше, чем успевает сбросить туда данные предыдущая итерация. Отсюда и "Access denied". Впрочем, может быть и ошибаюсь. :) А вообще предпочитаю не проводить множественные открытия-закрытия файлов, т.к. это сильно тормозит программу.

Re: Access denied при частом открытии файла

СообщениеДобавлено: 03.11.2008 21:09:32
Logo
Здесь видимо превышает допустимое количество открытых файлов. Тоесть, в цикле идет быстрая посылка комманд (сообщений) системе, система файлы откравыет, но закрывает с запаздыванием. Если нельзя изменить алгоритм, то побробуйте вставить Application.ProcessMessage после закрытия файла, да и после открытия можно (будет еще тормознутее :) ).

Re: Access denied при частом открытии файла

СообщениеДобавлено: 03.11.2008 21:18:11
shade
voltron писал(а):Файл-результат больше нигде не используется, после записи каждой порции данных закрывается.

Если результат больше нигде не используется, то может и не закрывать? Один раз открыл и пиши?...

Re: Access denied при частом открытии файла

СообщениеДобавлено: 04.11.2008 01:45:50
Padre_Mortius
тоже столкнулся с этой проблемой. Только работу с файлом оформил через потоки. Ошибка плавающая. Повторить ее получается крайне редко (у меня).

Код: Выделить всё
Procedure WriteToLog(Const FileStr, PathStr, Code: AnsiString);
Var
  LogStream: TFileStream;
  ResultStr, S, LogFileName: AnsiString;
Begin
  LogFileName := ExtractFilePath(ParamStr(0)) + 'Log\transport.log';
  ResultStr := Code;
  S := '';
  Try
    If Not FileExists(LogFileName) Then
      LogStream := TFileStream.Create(LogFileName, fmCreate)
    Else LogStream := TFileStream.Create(LogFileName, fmOpenWrite);
    LogStream.Seek(0, sofromEnd);
    If length(FileStr)<>0 Then ResultStr := StringReplace (Code, '%f', FileStr, [rfReplaceAll]);
    If length(PathStr)<>0 Then ResultStr := StringReplace (ResultStr, '%s', PathStr, [rfReplaceAll]);
    DateTimeToString(S, 'DD.MM.YYYY HH:NN:SS ', Now);
    ResultStr := S + ' ' + ResultStr + #13 + #10;
    LogStream.Write (PChar(ResultStr)[0], Length(ResultStr));
  Finally
    LogStream.Free;
  End;
End;