Форум программистов, компьютерный форум, киберфорум
Наши страницы
Delphi: WinAPI
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.65/17: Рейтинг темы: голосов - 17, средняя оценка - 4.65
dinamit-94
1 / 1 / 1
Регистрация: 20.10.2010
Сообщений: 56
1

Асинхронная запись в файл

16.12.2012, 01:35. Просмотров 3154. Ответов 14
Метки нет (Все метки)

Как строку str записать в файл report.rxr асинхронно(с использованием overlapped). Как на примере, только у меня последовательно. Хочу сделать параллельную запись
Delphi
1
2
3
4
5
6
7
8
9
procedure writetofile(const str: string);
var
    hfile: THandle;
    size: dword;
begin
     hfile := CreateFile('Report.txt',Generic_WRITE,0,nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
     writefile(hfile, PAnsiChar(str)^, length(str), size, nil);
     closehandle(hfile);
end;
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.12.2012, 01:35
Ответы с готовыми решениями:

Запись в файл
Всем привет! задача очень простая, в edit6.Text есть текст, его надо записать в...

Запись в файл
Memo1.Lines.SaveToFile('.\messages.txt'); Эта строка записывает в файл...

Запись таблицы в файл
Помогите записать таблицу в файл!!!!!Пожалуйста!!!! Вот текст программы ...

Запись текста в файл .txt
Здрасте.. Возникла необходимость в программе, которая бы 1)брала текст им...

Чтение\запись в файл структуру
есть код: type Files = record qu, answ: string; end; TFile =...

14
Alex_pac
1293 / 699 / 107
Регистрация: 25.05.2011
Сообщений: 2,158
Записей в блоге: 51
16.12.2012, 13:07 2
а это теоретически ваще возможно?
0
angstrom
2471 / 1847 / 242
Регистрация: 14.09.2012
Сообщений: 5,981
Записей в блоге: 2
16.12.2012, 14:17 3
Возможно, так делают Download-manager-ы. Только они первоначально создают файл необходимого размера (заполненный "мусором") и уже затем вписывают в него необходимые данные.
0
Alex_pac
1293 / 699 / 107
Регистрация: 25.05.2011
Сообщений: 2,158
Записей в блоге: 51
16.12.2012, 16:44 4
Возможно, так делают Download-manager-ы. Только они первоначально создают файл необходимого размера (заполненный "мусором") и уже затем вписывают в него необходимые данные.
может файл и создается, но еще может быть используется очередь записи. То есть некий алгоритм огранизует очередь записи между этими потоками и сводит асинхронную к линейной
0
angstrom
2471 / 1847 / 242
Регистрация: 14.09.2012
Сообщений: 5,981
Записей в блоге: 2
16.12.2012, 22:38 5
После создания файла и определённого количества потоков, каждому из них выделяется "свой" участок файла, куда нужно писать, и пересечься они не могут, соответственно и очередь не нужна
0
Alex_pac
1293 / 699 / 107
Регистрация: 25.05.2011
Сообщений: 2,158
Записей в блоге: 51
16.12.2012, 22:41 6
каждому из них выделяется "свой" участок файла
а с точки зрения кода это как будет выглядеть? если можно ссылку на реализацию или что либо с этим связанное, просто интересно.
0
dinamit-94
1 / 1 / 1
Регистрация: 20.10.2010
Сообщений: 56
17.12.2012, 00:32  [ТС] 7
В теории это так: в структуре Overlapped есть поле, обозначающее смещение в файле (32 разряда) и на всякий случай ( если файл больше 4 гб) - поле для смещения свыше 32 бит. При записи в файл, это поле нужно инкрементировать, на значение которое возращает один из параметров функции writefile , который равен количеству байт успешно записанных в файл. А синхрониризовать их надо объектом Event - дескриптор евента - одно из полей структуры Overlapped .
а на практике как то на получается=(

Добавлено через 1 час 7 минут
вот такой пример. но.. "запись потерпела неудачу" . в чем беда?

Delphi
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
procedure writetofile(const str: string);
var
 i: Integer;
  Memory: Double;
  SizeDir: Int64;
  FileHandle: THandle;
  OverLap: OVERLAPPED;
  res: BOOL;
  Swrite: String;
  Size: Integer;
  LastError,_WRITED: DWORD;
begin
Swrite := str;
  Size := SizeOf(Swrite);
  FileHandle := CreateFile('Protocol.txt', GENERIC_WRITE, 0,nil, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED,0);
  if FileHandle <> INVALID_HANDLE_VALUE then
    begin
      Overlap.hEvent := CreateEvent(0,True,False,0);
      res := WriteFile(FileHandle,Swrite,Size,_WRITED,@Overlap);
      LastError := GetLastError;
      ShowMessage('Г‡Г*ГЇГЁГ±Гј Г*Г*Г·Г*Г«Г*Г±Гј');
        if not res then
          if LastError = ERROR_IO_PENDING then
            while WaitForSingleObject(Overlap.hEvent,1000) = WAIT_TIMEOUT do
              Application.ProcessMessages
          else
        ShowMessage(' ÍåèçâåñòГ*Г*Гї îøèáêГ* ');
      GetOverlappedResult(FileHandle,Overlap,_WRITED,res);
      if not res then
        ShowMessage('Г‡Г*ГЇГЁГ±Гј ïîòåðïåëГ* Г*ГҐГіГ¤Г*Г·Гі');
      ShowMessage('Г‡Г*ГЇГЁГ±Гј Г§Г*ГЄГ®Г*Г·ГҐГ*Г*! Г‡Г*ГЇГЁГ±Г*Г*Г® ГЎГ*éò '+IntToStr(_WRITED));
      CloseHandle(Overlap.hEvent);
      CloseHandle(FileHandle);
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
26492 / 17792 / 7038
Регистрация: 22.10.2011
Сообщений: 31,310
Записей в блоге: 6
17.12.2012, 00:43 8
Цитата Сообщение от dinamit-94 Посмотреть сообщение
в чем беда?
А чего ты проверяешь Res после вызова GetOverlappedResult? Это In-параметр, он функцией не меняется, проверять надо сам результат GetOverlappedResult. И это, можно выложить хотя бы полностью процедуру, а не ее огрызок?
0
dinamit-94
1 / 1 / 1
Регистрация: 20.10.2010
Сообщений: 56
17.12.2012, 00:58  [ТС] 9
GetOverlappedResult тоже нуль возвращает=(
Это весь, end;end; лишь вставил
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
26492 / 17792 / 7038
Регистрация: 22.10.2011
Сообщений: 31,310
Записей в блоге: 6
17.12.2012, 01:24 10
Если GetOverlappedResult возвращает 0, то следующий вызов GetLastError покажет причину ошибки. Что он возвращает?
0
dinamit-94
1 / 1 / 1
Регистрация: 20.10.2010
Сообщений: 56
17.12.2012, 02:06  [ТС] 11
87: Параметр задан неверно.
будем искать?
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
26492 / 17792 / 7038
Регистрация: 22.10.2011
Сообщений: 31,310
Записей в блоге: 6
17.12.2012, 02:32 12
Ошибки, на самом деле, три:
1) не обнулена структура Overlap
2) не сброшен Event (для пущей надежности)
3) размер строки - это не SizeOf, а Length.

Итого:
Delphi
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
   ZeroMemory(@OverLap,sizeof(OverLap));
   Swrite := str;
   Size := Length(Swrite);
   FileHandle := CreateFile('F:\Protocol.txt', GENERIC_WRITE, 0, nil,
      OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, 0);
   if FileHandle <> INVALID_HANDLE_VALUE then
   begin
      Overlap.hEvent := CreateEvent(nil, True, False, nil);
      ResetEvent(OverLap.hEvent);
 
      if WriteFile(FileHandle,Swrite,Size,_WRITED, @Overlap) then
      begin
         ShowMessage('Запись началась');
         if LastError = ERROR_IO_PENDING then
            while WaitForSingleObject(Overlap.hEvent, 1000) = WAIT_TIMEOUT do
               Application.ProcessMessages
         else
            ShowMessage(' Неизвестная ошибка ');
 
         if not GetOverlappedResult(FileHandle,Overlap,_WRITED, True) then
         begin
            ShowMessage(Format('Запись потерпела неудачу : Error = %s',
               [SysErrorMessage(GetLastError)]));
         end
         else
            ShowMessage('Запись закончена! Записано байт ' + IntToStr(_WRITED));
      end
      else
         ShowMessage(Format('Запись потерпела неудачу : Error = %s',
            [SysErrorMessage(GetLastError)]));
 
      CloseHandle(Overlap.hEvent);
      CloseHandle(FileHandle);
   end
   else ShowMessage('Не удалось открыть файл');
1
dinamit-94
1 / 1 / 1
Регистрация: 20.10.2010
Сообщений: 56
17.12.2012, 03:17  [ТС] 13
Уже лучше. Но "Неизвестная ошибка" и каракули в файле...
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
26492 / 17792 / 7038
Регистрация: 22.10.2011
Сообщений: 31,310
Записей в блоге: 6
17.12.2012, 12:44 14
Хм... Надо мне больше спать, по-моему... Итак:

Delphi
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
procedure writetofile(const str: string);
var
  FileHandle: THandle;
  OverLap: OVERLAPPED;
  StringToWrite : string;
  Size: Integer;
  LastError, Written: DWORD;
begin
   ZeroMemory(@OverLap,sizeof(OverLap));
   StringToWrite := str;
   Size := Length(StringToWrite) * SizeOf(Char); // Юникодные версии Дельфи
 
   FileHandle := CreateFile('F:\Protocol.txt', GENERIC_WRITE, 0, nil,
      OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, 0);
   if FileHandle <> INVALID_HANDLE_VALUE then // Файл создан?
   begin
      // Да, все нормально, продолжаем. Создаем Event и сбрасываем его
      Overlap.hEvent := CreateEvent(nil, True, False, nil);
      ResetEvent(OverLap.hEvent);
 
      // Тут у нас запись началась в любом случае, ведь WriteFile вызывается.
      // Ошибки будем обрабатывать позже
      Form1.Memo3.Lines.Add('Запись началась');
 
      // Теперь о вызове WriteFile. Внимательно смотрим на второй параметр. Так передаются строки
      if not WriteFile(FileHandle, StringToWrite[1], Size, Written, @Overlap) then
      begin
 
         // Обработка ошибок. Если WriteFile вернула False, но при этом GetLastError = ERROR_IO_PENDING
         // Значит, это была не ошибка, и надо дождаться окончания записи
         LastError := GetLastError;
         if LastError = ERROR_IO_PENDING then
            while WaitForSingleObject(Overlap.hEvent, 1000) = WAIT_TIMEOUT do
               Application.ProcessMessages
         else
            // А вот если не ERROR_IO_PENDING - то была ошибка, рассказываем пользователю об этом
            Form1.Memo3.Lines.Add(Format('WriteFile. Ошибка: Error = %s',
               [SysErrorMessage(GetLastError)]))
            (*
            ShowMessage(Format('WriteFile. Ошибка: Error = %s',
               [SysErrorMessage(GetLastError)]));
            *)
      end;
      // Эта часть вообще не нужна. Если WriteFile вернула True - то всё в порядке
      (*
      else
         ShowMessage(Format('Запись потерпела неудачу : Error = %s',
            [SysErrorMessage(GetLastError)]));
      *)
 
      // А вот теперь смотрим, что даёт GetOverlappedResult
      if not GetOverlappedResult(FileHandle, Overlap, Written, True) then
      begin
         Form1.Memo3.Lines.Add(Format('GetOverlappedResult. Запись потерпела неудачу : Error = %s',
            [SysErrorMessage(GetLastError)]));
         (*
         ShowMessage(Format('GetOverlappedResult. Запись потерпела неудачу : Error = %s',
            [SysErrorMessage(GetLastError)]));
         *)
      end
      else
         Form1.Memo3.Lines.Add(Format('Запись закончена! Записано байт %d', [Written]));
         // ShowMessage(Format('Запись закончена! Записано байт %d', [Written]));
 
      CloseHandle(Overlap.hEvent);
      CloseHandle(FileHandle);
   end
   else
      Form1.Memo3.Lines.Add('Не удалось открыть файл');
      // ShowMessage('Не удалось открыть файл');
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
   writetofile('Just a test');
end;
1
dinamit-94
1 / 1 / 1
Регистрация: 20.10.2010
Сообщений: 56
17.12.2012, 14:48  [ТС] 15
Похоже на то, спасибо!
0
17.12.2012, 14:48
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.12.2012, 14:48

Запись в динамически создаваемый файл
Здравствуйте. проблема такая: я создаю файл и хочу записать в него текст из...

В dat файл записывается всего одна запись
У меня в этот файл записывается всего одна запись когда записываешь второй раз...

Запись разнообразных данных в бинарный файл (как лучше сделать?)
Собственно вопрос таков, имеются очень много структур данных(записи), как их...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru