Форум «Всё о Паскале» _ Делфи _ Сохранение данных Memo
Автор: Jill 30.03.2006 17:44
Не получается
С SaveDialog получается, но...
Задача на потоки. В одном из потоков необходимо данные Memo сохранять в текстовый файл. Как?
Автор: hiv 30.03.2006 18:02
Примерно так:
var fs:TFileStream; ... begin ... fs:=TFileStream.Create(SaveDialog1.FileName,fmOpenWrite); memo1.Lines.SaveToStream(fs); fs.Free; end;
Автор: Jill 30.03.2006 18:06
hiv, заморочка у меня такая:
где именно вписывать имя выходного файла? как его вписывать?
и где и как этот файл обьявлять?
Автор: hardcase 30.03.2006 20:46
Зачем объявлять файл? Файлы (file of ...) остались в Pascal - в делфи их использовать не рекомендуется, а в старших версиях Делфи они вообще запрещены.
var fs: TStream;
begin if SaveDialog1.Execute then begin //запускаем SaveDialog fs:=TFileStream.Create(SaveDialog1.FileName, fmCreate or fmOpenWrite); Memo1.Lines.SaveToStream(fs); fs.Free; end;
ещё вариант:
var fn: string; fs: TStream;
begin fn:=InputBox('Output file','Enter file name:','C:\test.txt'); fs:=TFileStream.Create(fn, fmCreate or fmOpenWrite); Memo1.Lines.SaveToStream(fs); fs.Free; end;
Автор: Jill 31.03.2006 13:33
hardcase, файл должен сохранятся по умолчанию
почему не проходит такой вариант?
var f:TextFile; fName:string[80]; i:integer; begin fName:='CallRecord.txt'; AssignFile(f,fName); Rewrite(f); for i:=0 to Form1.Memo1.Lines.Count do begin writeln(f,Form1.Memo1.Lines[i]); end; CloseFile(f); end;
вроде работает в потоке...
Автор: #$# PaVeL #$# 31.03.2006 15:46
По моему лучше сделать так:
Memo1.Lines.SaveToFile(FileName);
,где FileName - это имя файла (возможно с директорией) в который сохраняется содержимое компонента Memo1
Всё гениальное - просто!
Почти тоже самое только одной строчкой кода!
Автор: Jill 31.03.2006 16:55
запускается...
тока перестает реагировать на кнопку стоп и притормаживает...
Автор: hiv 31.03.2006 17:16
Цитата(Jill @ 31.03.2006 9:33)
hardcase, файл должен сохранятся по умолчанию
почему не проходит такой вариант?
var f:TextFile; fName:string[80]; i:integer; begin fName:='CallRecord.txt'; AssignFile(f,fName); Rewrite(f); for i:=0 to Form1.Memo1.Lines.Count do begin writeln(f,Form1.Memo1.Lines[i]); end; CloseFile(f); end;
вроде работает в потоке...
Потому, что надо:
... for i:=0 to Form1.Memo1.Lines.Count-1 do begin ...
И где здесь потоки?
Сделай как написал тебе hardcase в своем первом примере, только не забудь кинуть на форму SaveDialog из ярлычка Dialogs в панели компонентов. Хау!
Автор: Jill 31.03.2006 17:35
ребят, мне необходимо сохранять файл ПО УМОЛЧАНИЮ, без выбора директории а во всех предложениях нужно выбрать папку
с первым примером hardcase вылазит предложение о выборе папки (выбрать ее невозможно) и прога не прерывается
(у меня два потока - в одном запись формируется - в другом должна сохраняться)
Автор: hiv 31.03.2006 19:02
Цитата
С SaveDialog получается, но...
Мы тут не занимаемся спиритизмом! Давай код в студию. Может ты путаешься в понятии, что такое поток!
var Form1: TForm1; T1 : TCreateRecord; T2 : TSaveRecord;
implementation
{$R *.dfm}
procedure TForm1.FormShow(Sender: TObject); begin Form1.Memo1.Clear; end;
procedure TCreateRecord.Execute; begin {Пока процесс не прервали, выполняем DoWork} while not Terminated do Synchronize(DoWork); end;
procedure TSaveRecord.Execute; begin {Пока процесс не прервали, выполняем DoWork} while not Terminated do Synchronize(DoWork); end;
{Телефон абонента} function GenerateTelAbon:string; var nom:integer; begin nom:=random(899999)+100000; GenerateTelAbon:=' 8-375-16-'+IntToStr(nom); end;
function GenerateTel:string; var k,ks,kg,nom:integer; pr,pr1:string; Kod:Array[1..2] of integer; begin Kod[1]:=8; Kod[2]:=10; k:=random(2)+1; ks:=random(899)+100; kg:=random(89)+10; nom:=random(899999)+100000; if Kod[k]=10 then begin pr:=' '; pr1:=' '; end else begin pr:=' '; pr1:=' '; end; GenerateTel:=' '+pr+IntToStr(Kod[k])+'-'+IntToStr(ks)+'-'+IntToStr(kg)+'-'+IntToStr(nom)+pr1; end;
{Дата} function GenerateDate:string; var d,m:integer; day,month:string; begin m:=random(12); if m=2 then d:=random(28); if (m=1)or(m=3)or(m=5)or(m=7)or(m=8)or(m=10)or(m=12) then d:=random(31) else d:=random(30); day:=IntToStr(d); if Length(day)=1 then day:='0'+day; month:=IntToStr(m); if Length(month)=1 then month:='0'+month; GenerateDate:=day+'.'+month+'.'+'2006 '; end;
{Начало и конец разговора} function GenerateTimeStartFinish:string; var h,m:integer; hour,minute:string; begin h:=random(24); hour:=IntToStr(h); if Length(hour)=1 then hour:='0'+hour; if hour='24' then hour:='00'; m:=random(60); minute:=IntToStr(m); if Length(minute)=1 then minute:='0'+minute; if hour='60' then minute:='00'; GenerateTimeStartFinish:=hour+':'+minute; end;
{Продолжительность разговора} function GetTime(start,finish:string):string; var h1,h2,m1,m2,m:integer; hour1,hour2,minute1,minute2,minute:string; begin hour1:=start[1]+start[2]; h1:=StrToInt(hour1); h1:=h1*60; minute1:=start[4]+start[5]; m1:=StrToInt(minute1); m1:=m1+h1;
m:=m2-m1; if m<0 then m:=m+1440; minute:=IntToStr(m); if Length(minute)=1 then minute:=minute+' '; if Length(minute)=2 then minute:=minute+' '; if Length(minute)=3 then minute:=minute+' '; if Length(minute)=4 then minute:=minute+' '; GetTime:=minute; end;
{Идентификатор линии} function GenerateIdent:string; var i:integer; id:Array[1..5] of string; iden:string; begin id[1]:='C'; id[2]:='O'; id[3]:='I'; id[4]:='S'; id[5]:='R'; i:=random(5)+1; iden:=id[i]; GenerateIdent:=iden; end;
procedure TCreateRecord.DoWork; var start,finish,s:string; begin s:=' '; begin start:=GenerateTimeStartFinish; finish:=GenerateTimeStartFinish; Form1.Memo1.SelText:=GenerateTelAbon+GenerateTel+GenerateDate+ Start+s+Finish+s+GetTime(start,finish)+s+GenerateIdent+#13#10; end;
end;
procedure TSaveRecord.DoWork; var f:TextFile; fName:string[80]; i:integer; begin fName:='CallRecord.txt'; AssignFile(f,fName); Rewrite(f); for i:=0 to Form1.Memo1.Lines.Count do begin if i=0 then writeln(f,' '+Form1.Label1.Caption+' ' +Form1.Label2.Caption+' '+Form1.Label3.Caption+ ' '+Form1.Label4.Caption+' '+Form1.Label5.Caption+ ' '+Form1.Label6.Caption+' '+Form1.Label7.Caption) else writeln(f,Form1.Memo1.Lines[i]); end; CloseFile(f); end;
procedure TForm1.Button1Click(Sender : TObject); begin Button1.Enabled:=False; Button2.Enabled:=True; T1:=TCreateRecord.Create(False); T2:=TSaveRecord.Create(False); end;
procedure TForm1.Button2Click(Sender : TObject); begin T1.Terminate; T2.Terminate; Button1.Enabled:=True; Button2.Enabled:=False; end;
end.
ууупс...можно же было порезать для удобочитаемости...
Автор: hardcase 31.03.2006 20:02
Хм. Код конечно странный. Сейчас посмотрел. Когда пишиешь многопоточные приложения стоит их хоть как-то комментировать. Ты не могла бы описать, что делает сей код? Я вижу две разные нитки (ты их называешь потоками)... И я так вижу, что TSaveRecord на каждой своей итерации должен сохранять инфу. Зачем тебе ПОСТОЯННО это делать?
Напиши формулировку совоего задания. Наверняка всё можно сделать ГОРАЗДО проще, чем у тебя сейчас есть. Говорю тебе, как человек, который на нитках не одну собаку съел.
Автор: Jill 31.03.2006 20:09
Постановка задачи: Написать программу, которая формирует запись о звонке и записывает ее в текстовый файл . В программе должно быть реализовано несколько потоков. Запись о звонке формируется в одном и передается в другой поток. В другом потоке она записывается в выходной текстовый файл.
Суть в принципе такова - в поле Мемо формируется запись (поток1,TCreateRecord, вроде работает) В потоке 2 (TSaveRecord) эти данные должны сохраняться
Автор: volvo 31.03.2006 20:54
Цитата
Говорю тебе, как человек, который на нитках не одну собаку съел.
Значит, мало съел! Придется повторить трапезу.
Уважаемый hardcase, возможно, снизойдет до объяснения всем остальным участникам форума, В ЧЕМ по его мнению заключается разница между нитью (thread) и потоком (опять же thread, странно, правда?) ? Только БЕЗ раскидывания понтов типа "А крутые пацаны в нашем городе привыкли треды называть нитями, не как все остальные ламеры..."
Автор: hardcase 1.04.2006 3:47
Вот мой вариант работы с нитками (так называть предпочтительнее потому как может возникнуть путаница со стримами):
Исходный код
// решение классической задачи о поставщике // и получателе (в классическом варианте используются // два семафора)
const //имя файла, куда будем сохранять RECORD_FILE = 'file.txt';
// класс нашей записи type TSaveRecord = class private fLine: string; public constructor Create; property Line: string read fLine; end;//of class
// в конструкторе втупую создаём новую строку // ты можешь заменить на всё, что тебе нужно
var i: integer = 1; constructor TSaveRecord.Create; begin fLine:='Text record #'+IntToStr(i); inc(i); end;
var // текущая запись Rec: TSaveRecord = nil;
// это специальный объект, который позволяет синхронизировать // чтение/запись в переменную Rec Mtx: TMultiReadExclusiveWriteSynchronizer;
// наш потребитель - получает новую запись // и сохраняет в файл type TRecordSaver = class(TThread) private fStream: TStream; procedure UpdateMemo; procedure WriteRec; public procedure Execute; override; end;//of class
// процедура отображает новую запись в Memo // компонент на форме procedure TRecordSaver.UpdateMemo; begin Form1.Memo1.Lines.Add(Rec.Line); end;
// процеура чтения новой записи procedure TRecordSaver.WriteRec; var S: string; begin // бликируем Rec для изменения из поставщика Mtx.BeginRead; try if Rec = nil then Exit; // переходим к блоку finally если Rec пуста // пишем в файл S:=Rec.Line+#13#10; fStream.WriteBuffer(pointer(S)^,Length(S));
//отображаем в Мемо Synchronize(UpdateMemo);
// Rec нам больше не нужна FreeAndNil(Rec); finally // не забываем разблокировать Mtx.EndRead; end; end;
procedure TRecordSaver.Execute; begin // открываем файл для записи fStream:=TFileStream.Create(RECORD_FILE,fmCreate or fmOpenWrite); try while not Terminated do begin WriteRec; // небольшая задержка Sleep(100); end; finally fStream.Free; end; end;
// наш поставщик type TRecordGenerator = class(TThread) private procedure GenerateRec; protected procedure Execute; override; end;//of class
procedure TRecordGenerator.GenerateRec; begin // блокируем Rec для чтения из другого потока Mtx.BeginWrite; try // создаём новую запись if Rec = nil then // предыдущая запись прочитана Rec:=TSaveRecord.Create; finally // снимаем блокировку Mtx.EndWrite; end; end;
procedure TRecordGenerator.Execute; begin while not Terminated do begin GenerateRec; // опятьже задержка Sleep(100); end; end;
var Saver: TRecordSaver; Generator: TRecordGenerator;
procedure TForm1.FormCreate(Sender: TObject); begin // создали синхронизатор Mtx:=TMultiReadExclusiveWriteSynchronizer.Create; end;
procedure TForm1.FormDestroy(Sender: TObject); begin Button2.Click; end;
procedure TForm1.Button1Click(Sender: TObject); begin //защита от дурака if (Saver <> nil) or (Generator <> nil) then Exit;
// создали потребителя Saver:=TRecordSaver.Create(true);
// создали пославщика Generator:=TRecordGenerator.Create(true);
procedure TForm1.Button2Click(Sender: TObject); begin // уничтожаем поставщика if Generator <> nil then begin Generator.Terminate; Generator.WaitFor; FreeAndNil(Generator); end; // уничтожаем потребителя if Saver <> nil then begin Saver.Terminate; Saver.WaitFor; FreeAndNil(Saver); end; end;
На форму положить: Memo - 1 штук; Button - 2 штуки; также подсоединить событие создания формы и разрушения (в моем коде они определены)
Автор: hiv 3.04.2006 14:26
Если надо использовать метод Synchronize, то вот так переделать: Unit1.pas ( 5.31 килобайт )
Кол-во скачиваний: 517