Консультация № 51910
12.08.2006, 02:07
0.00 руб.
0 4 3
Здравствйте, господа Эксперты! Огромное спасибо всем, кто отвечал на мой вопрос № 51689 про перезапись структур.
К сожалению, он так и не решился. Наверное, я не точно его задал или меня не совсем поняли: я НЕ имел в виду запись нескольких структур за 1 раз - я знал, что в цикле прекрасно записывается любое кол-во структур, но зачем мне одно и то же несколько раз? Я подробнее обрисую мою ситуацию, может это поможет.
Я пишу для компании психолог. тест - оболочку для него. Естественно, должна быть база вопросов, которая будет редактироваться. Я решил использовать для нее типизированный файл. Т.е. сел человек,открыл редактор вопросов, в Memo ввел ворос, в 4 Editа - варианты ответа, нажал кнопку - вопрос и варианты записались в структуру, которая потом записалась в файл, а Memo и Editы очистились - можно писать следующий вопрос, а все структуры в файле должны идти по очереди - меняются только вопросы и варианты - по-моему, удобно. Сам тест просто читает структуру и заполняет соответствующие поля на своей форме.
Проблема в том, что и моя запись одной структуры, и предложение экспертов писать в цикле все-равно перезаписываются - повесьте цикл for i:=0 to 1 на кнопку и нажмите ее 2 раза, а потом откройте файл и посмотрите - там будет не 4 структуры, а 2. Вот что я имел в виду! А мне надо за каждое нажатие кнопки записывать всего 1 структуру, но чтобы они все оставались в файле. Смена режима fmCreate на fmOpenReadWrite + Seek не помогает. Помогите, пожалуйста, сроки сдачи приближаются!

Обсуждение

Неизвестный
12.08.2006, 06:12
общий
это ответ
Здравствуйте, Neiroman!
У меня есть подозрение, что TFileStream как истинный поток не может позиционироваться от конца потокаТогда для позиционирования на конец файла надо сдвинуться от начала soFromBegining на число байт, равному размеру файла.
Ниже в приложении рабочий вариант.

Приложение:
procedure TForm1.Button1Click(Sender: TObject);type TFileRec = record Quest, Answer1, Answer2 : array [0..255] of char; end;var Buf : TFileRec; F : TFileStream;begin FillChar(Buf.Quest, SizeOf(Buf.Quest), ‘ ‘); FillChar(Buf.Answer1, SizeOf(Buf.Answer1), ‘ ‘); FillChar(Buf.Answer2, SizeOf(Buf.Answer2), ‘ ‘); StrCopy(Buf.Quest, PChar(Memo1.Text)); StrCopy(Buf.Answer1, PChar(Edit1.Text)); StrCopy(Buf.Answer2, PChar(Edit2.Text)); F := TFileStream.Create(‘c:\1.dat‘,fmOpenReadWrite); F.Seek(F.Size,soFromBeginning); F.WriteBuffer(Buf,SizeOf(Buf)); F.Free;end;
Неизвестный
12.08.2006, 06:17
общий
это ответ
Здравствуйте, Neiroman!
Я использовал для работы с файлами старые (но прекрасно работающие) паскалевские процедуры. Посмотрите еще вот эту статью: http://delphiworld.narod.ru/base/object_pascal_db.html
Надеюсь, все будет понятно. Если что - в минифорум или вн. почту.

Приложение:
unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;type TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; TUserInfo = record Group: string[4]; Name: string[30]; end;var Form1: TForm1; f:file of TUserInfo; user:TUserInfo;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);beginuser.Name:=edit1.Text;user.Group:=edit2.Text;assignfile (f, ‘users.txt‘);reset (f);Seek(F, FileSize(F));write (F, user);closefile (f);end;procedure TForm1.Button2Click(Sender: TObject);beginAssignFile(F,‘users.txt‘); Reset(F); try while not Eof(F) do begin read (F, user); showmessage (user.Group+‘ ‘+user.Name); end; finally CloseFile(F); end;end;end.
Неизвестный
12.08.2006, 08:52
общий
это ответ
Здравствуйте, Neiroman!

У меня всё прекрасно работает и через fmOpenReadWrite + Seek:

Приложение:
procedure TForm1.Button1Click(Sender: TObject);var FStr:TFileStream; User:TUserInfo; mode:word; filename:string;begin filename:=‘C:\temp\results.txt‘; if FileExists(filename) then mode:=fmOpenReadWrite else mode:=fmCreate; FStr:=TFileStream.Create(filename,mode); FStr.Seek(0,soFromEnd); User.Group:=‘Group‘; User.Name:=‘MyName‘; User.Limit:=60; User.EndTime:=DateTimeToStr(Now); FStr.Write(User,SizeOf(TUserInfo)); FStr.Free;end;
Неизвестный
12.08.2006, 16:09
общий
2Neiroman:У Physicist точно правильный код. Вы, похоже, в процедуре нажатия кнопки заново создавали файл. Вот он и "обнулялся". Соответственно, его надо либо созать через проводник и всегда в него писать, либо использовать конмтрукцию эксперта Physicist:if FileExists(filename) then mode:=fmOpenReadWrite else mode:=fmCreate;2Morgen_krsk: Ваше подозрение логично... но кто мешал написать процедуру для потоков (при разработке класса) и добавить в нее вариант позиционирования с конца:function TStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;begin ... if Origin = soFromEnd then Seek(Self.Size - Offset, soFromBeginning)end;На самом деле в Classes.pas написано нечто совсем другоено это не принципиально.2Coupler: Использовать старые процедуры... ну, понятно, что плохоЕсли бы программа писалась для себя, это было бы нормально. Но для коммерческого продукта такого лучшне не делать. Вот не будет программа работать на Widows Vista из-за несовместимости - переписывать? А потоки там точно останусься.
Форма ответа