Помощь - Поиск - Пользователи - Календарь
Полная версия: Сохранение данных Memo
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
Jill
Не получается unsure.gif

С SaveDialog получается, но...

Задача на потоки. В одном из потоков необходимо данные Memo сохранять в текстовый файл. Как?
hiv
Примерно так:
var fs:TFileStream;
...
begin
...
fs:=TFileStream.Create(SaveDialog1.FileName,fmOpenWrite);
memo1.Lines.SaveToStream(fs);
fs.Free;
end;
Jill
hiv, заморочка у меня такая:

где именно вписывать имя выходного файла? как его вписывать?

и где и как этот файл обьявлять?
hardcase
Зачем объявлять файл?
Файлы (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
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 #$#
По моему лучше сделать так:
Memo1.Lines.SaveToFile(FileName);

,где FileName - это имя файла (возможно с директорией) в который сохраняется содержимое компонента Memo1

Всё гениальное - просто! blink.gif smile.gif blink.gif smile.gif

Почти тоже самое только одной строчкой кода!
Jill
запускается...

тока перестает реагировать на кнопку стоп и притормаживает... blink.gif
hiv
Цитата(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
ребят, мне необходимо сохранять файл ПО УМОЛЧАНИЮ, без выбора директории
а во всех предложениях нужно выбрать папку

с первым примером hardcase вылазит предложение о выборе папки (выбрать ее невозможно) и прога не прерывается


(у меня два потока - в одном запись формируется - в другом должна сохраняться)
hiv
Цитата
С SaveDialog получается, но...

Мы тут не занимаемся спиритизмом!
Давай код в студию. Может ты путаешься в понятии, что такое поток!
Jill
ок smile.gif просто код длинноват:

Исходный код
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Mask, ComCtrls, Buttons;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
ScrollBox1: TScrollBox;
Memo1: TMemo;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
procedure FormShow(Sender: TObject);
procedure Button1Click(Sender : TObject);
procedure Button2Click(Sender : TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
TCreateRecord = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;

TSaveRecord = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;

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;

hour2:=finish[1]+finish[2]; h2:=StrToInt(hour2);
h2:=h2*60;
minute2:=finish[4]+finish[5]; m2:=StrToInt(minute2);
m2:=m2+h2;

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
Хм. Код конечно странный. Сейчас посмотрел.
Когда пишиешь многопоточные приложения стоит их хоть как-то комментировать. Ты не могла бы описать, что делает сей код?
Я вижу две разные нитки (ты их называешь потоками)...
И я так вижу, что TSaveRecord на каждой своей итерации должен сохранять инфу. Зачем тебе ПОСТОЯННО это делать?

Напиши формулировку совоего задания. Наверняка всё можно сделать ГОРАЗДО проще, чем у тебя сейчас есть. Говорю тебе, как человек, который на нитках не одну собаку съел.
Jill
Постановка задачи:
Написать программу, которая формирует запись о звонке и записывает ее в текстовый файл .
В программе должно быть реализовано несколько потоков.
Запись о звонке формируется в одном и передается в другой поток.
В другом потоке она записывается в выходной текстовый файл.


Суть в принципе такова - в поле Мемо формируется запись (поток1,TCreateRecord, вроде работает)
В потоке 2 (TSaveRecord) эти данные должны сохраняться
volvo
Цитата
Говорю тебе, как человек, который на нитках не одну собаку съел.
Значит, мало съел! Придется повторить трапезу.

Уважаемый hardcase, возможно, снизойдет до объяснения всем остальным участникам форума, В ЧЕМ по его мнению заключается разница между нитью (thread) и потоком (опять же thread, странно, правда?) ? Только БЕЗ раскидывания понтов типа "А крутые пацаны в нашем городе привыкли треды называть нитями, не как все остальные ламеры..."
hardcase
Вот мой вариант работы с нитками (так называть предпочтительнее потому как может возникнуть путаница со стримами):
Исходный код

// решение классической задачи о поставщике
// и получателе (в классическом варианте используются
// два семафора)

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);

Memo1.Clear;

// поехали!!!
Saver.Resume;
Generator.Resume;
end;

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
Если надо использовать метод Synchronize, то вот так переделать:
Нажмите для просмотра прикрепленного файла
Jill
спасибо всем smile.gif за помощь, примеры и варианты

отдельно спасибо hiv - это то, что надо!!! пасиба smile.gif
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.