Текущий архив: 2002.07.29;
Скачать: CL | DM;
ВнизПотоки Найти похожие ветки
← →
Leny (2002-07-15 08:20) [0]Уважаемые мастера! Мне необходимо пересалать данные, находящиеся в таблице StringGrid. Данные расположены по строкам.
Я создала тип запись
S: record
Name: string;
Age: Integer;
end;
Создаю поток ms:= TMemoryStream.Create;
Теперь мне надо записать в поток Переменную S.
Как это сделать? Этих S может быть 5 - поэтому придется посылать в цикле... Можно ли это сделать и как?
← →
MBo (2002-07-15 08:26) [1]vS:array[1..5] of S;
ms:= TMemoryStream.Create;
for i:=1 to 5 do begin
l:=length(vs[i].Name);
ms.Write(l,SizeOf(l);//пишем длину строки! при чтении исп. SetLength
ms.Write(vs[i].Name[1],l);
ms.Write(vs[i].Age,SizeOf(Integer));
end;
← →
Leny (2002-07-15 08:55) [2]А если я не знаю сколько будет S - может быть пять, а может и 20...
То как я задам массив?
Можно как-нибудь обойтись без vS:array[1..5] of S;
Например, считывать данные из каждой ячейки в каждой строке и посылать построчно?
И как принять эти данные и записать их снова в таблицу?
← →
Anatoly Podgoretsky (2002-07-15 09:02) [3]Да можно, копать в сторону динамических массивов,
объявление будет выглядеть так vS:array of S;
выделение места в массиве так Setlength(vS,StringGrid.Count);
Но по твоей задаче массив совсен не требуется, хватает одного экземпляра S или вообще не требуется, прямо брать данные из StringGrid
← →
Lord Warlock (2002-07-15 09:03) [4]Использовать динамический массив
vS:array of S;
SetLength(vS,Grid1.RowCount)
for i:=0 to Length(vS)-1 do
begin
...
далее см MBo © (15.07.02 08:26)
← →
MBo (2002-07-15 09:03) [5]>считывать данные из каждой ячейки в каждой строке и посылать построчно
Да, безусловно можно.
Но проще воспользоваться свойством Text каждой строки (Rows) StringGrid
var s:string;
ms:= TMemoryStream.Create;
l:=RowCount-FixedRows;
ms.Write(l,SizeOf(l);//пишем количество строк
with StringGrid1 do
for i:=FixedRows to RowCount-1 do begin
s:=Rows[i].Text;
l:=length(s);
ms.Write(l,SizeOf(l);//пишем длину строки! при чтении исп. SetLength
ms.Write(s[1],l);
end;
← →
Leny (2002-07-15 10:06) [6]А как получить данные и записать их в таблицу?
← →
MBo (2002-07-15 10:13) [7]>А как получить данные и записать их в таблицу?
Я так и подозревал ;)
не забудь и о количестве столбцов, если оно разное
var s:string;
ms.read(l,SizeOf(l);//пишем количество строк
with StringGrid2 do begin
RowCount:=l+FixedRows;
for i:=FixedRows to RowCount-1 do begin
ms.read(l,SizeOf(l));
setlength(s,l);
ms.read(s[1],l);
Rows[i].Text:=s;
end;
end;
← →
Leny (2002-07-15 10:25) [8]Здесь опять встречается ms - ее задавать глобально?
Это ведь должна быть одна и та же переменная...
← →
MBo (2002-07-15 10:26) [9]ну да, поток ведь один. Если его освободить, данные пропадут.
А какая исходная задача? может, ьез потока обойтись можно?
← →
Leny (2002-07-15 10:34) [10]Задача такова.
В таблицу записываются пути нескольких файлов(графических)+их характеристики(размер и пр.) нужно послать эти файлы (вместе со всеми характеристиками) на сервер. При этом они должны записаться в такую же таблицу.
Т.е по существу скопировать таблицу с одного компьютера на другой...
← →
Leny (2002-07-15 11:01) [11]у меня есть локальная сеть... Так что одновременно могут посылать данные 2 и более пользователей.
Поэтому, я думаю, нужно для каждого создавать свой поток...
И еще... При копировании таблицы желательно, чтобы сами файлы копировались в опред.папку на отдельном компьютере.
← →
kig (2002-07-15 11:14) [12]У Вас каждый клиент (пользователь) куда посылает таблицу? На какой сервер? На отдельную машину в виде чего-то там, или под сервером Вы подразумеваете Ваш собственный Application Server?
"
у меня есть локальная сеть... Так что одновременно могут посылать данные 2 и более пользователей.
Поэтому, я думаю, нужно для каждого создавать свой поток...
"
В где создавать? В AppServer или?
← →
Leny (2002-07-15 11:40) [13]Под сервером я подразкмеваю отдел.машину, куда все посылают свои данные. А потоки создавать при запуске программы на этом сервер(если это возможно).
← →
kig (2002-07-15 11:46) [14]"
А потоки создавать при запуске программы на этом сервер(если это возможно).
"
Да в программе на сервере (машине) можно делать все, что угодно.
К клиентам-то это каким боком? Ну создал клиент поток - возможно сразу TFileStream, сбросил туда таблицу - на сервер (машина) появился в определенном месте файл (ну ряд файлов графики).
Это я так представил весь процесс по всем сообщениям ветки.
А далее то что предполагается? с этими файлами на сервере делать?
Или я не правильно представил себе архитектуру задачи?
← →
Leny (2002-07-15 11:53) [15]В общем-то все правильно...
Дальше на сервере открываются эти файлы и обрабатываются(если необходимо) , притом обработанные файлы складываются в опред.папку.
← →
kig (2002-07-15 12:14) [16]Ну на сервере (машине) тогда проще повесить приложенице и обрабатывать поступающие файла последовательно. Один файл обрабатываем - ну и заводим ресурсы (потоки и т.п.) на него.
Обработали - смотрим - есть еще .... ну и так по кругу.
Запускать это приложенице можно ... да хоть через Task Manager (Tasks).
Если Вам критично использование TStringGrid - то посмотрите на св-во Rows[i] - это TStrings, а TStrings имеет методы SaveToStream/LoadFromStream.
Если не критично - можно воспользоваться или TClientDataSet, или TADODataSet без привязки к БД (без коннекта). Оба умееют сохранять себя в файл и восстанавливать себя из него.
А на клиенте DBGrid связанный с этим набором данных. В наборе данных заранее созданы колонки, те, которые Вам необходимы (путь, размер и т.д.) Кстати, и Вам будет проще - например, в колонку "размер" можно будет ввести только число...
← →
kig (2002-07-15 12:16) [17]... если конечно колонка "размер" будет иметь числовой тип...
))
← →
Leny (2002-07-15 12:26) [18]Здесь есть одно НО...
мне не нужно в программе обрабатывать файл
Мне нужно всего лишь скопировать таблицу! И именно таблицей, а не отдельными строками, т.к каждая таблица ассоциируется с опр.пользователем.
← →
kig (2002-07-15 13:17) [19]Ну и кто Вам мешает? Имено целиком?
Или я во что-то не въехал?
Вот клиент создал файл, содержащий талицу, и сохранил его на сервере. Какова дальнейшая его судьба?
← →
Случайный прохожий (2002-07-15 16:56) [20]Может выглядеть примерно так:
unit TransportGrid;
interface
uses
Classes, Windows, Grids;
type
TStgStrings = class(TStrings)
public
procedure StgSaveToStream(Stream: TStream);
procedure StgLoadFromStream(Stream: TStream);
end;
procedure SendGrid(TransportHandle: THandle; Grid: TStringGrid);
function GetGrid(TransportHandle: THandle; GridOwner: TComponent):TStringGrid;
implementation
{ TStgStrings }
procedure TStgStrings.StgLoadFromStream(Stream: TStream);
var
Size: Integer;
S: string;
begin
BeginUpdate;
try
Stream.Read(Size,SizeOf(Size));
SetString(S, nil, Size);
Stream.Read(Pointer(S)^, Size);
SetTextStr(S);
finally
EndUpdate;
end;
end;
procedure TStgStrings.StgSaveToStream(Stream: TStream);
var
S: string;
n:integer;
begin
S := GetTextStr;
n:=Length(s);
Stream.Write(n,SizeOf(n));
Stream.WriteBuffer(Pointer(S)^, n);
end;
procedure SendGrid(TransportHandle: THandle; Grid: TStringGrid);
var
MS:TMemoryStream;
Rows, n: Cardinal;
begin
MS:=TMemoryStream.Create;
try
MS.Position:=4;
Rows:=Grid.ColCount;
MS.Write(Rows,SizeOf(Rows));
Rows:=Grid.RowCount;
MS.Write(Rows,SizeOf(Rows));
for n:=0 to Pred(Rows) do
TStgStrings(Grid.Rows[n]).StgSaveToStream(MS);
MS.Position:=0;
Rows:=MS.Size-3*SizeOf(Rows);
MS.Write(Rows,SizeOf(Rows));
WriteFile(TransportHandle,MS.Memory^,MS.Size,n,nil);
finally
MS.Free;
end;
end;
function GetGrid(TransportHandle: THandle; GridOwner: TComponent):TStringGrid;
var
MS:TMemoryStream;
Rows, n: Cardinal;
begin
MS:=TMemoryStream.Create;
try
ReadFile(TransportHandle,Rows,SizeOf(Rows),n,nil);
MS.Size:=Rows;
Result:=TStringGrid.Create(GridOwner);
ReadFile(TransportHandle,Rows,SizeOf(Rows),n,nil);
Result.ColCount:=Rows;
ReadFile(TransportHandle,Rows,SizeOf(Rows),n,nil);
Result.RowCount:=Rows;
ReadFile(TransportHandle,MS.Memory^,MS.Size,n,nil);
MS.Position:=0;
for n:=0 to Pred(Result.RowCount) do
TStgStrings(Result.Rows[n]).StgLoadFromStream(MS);
finally
MS.Free;
end;
end;
end.
Тестовый код:
var
FFile: THandle;
procedure TForm2.Button1Click(Sender: TObject);
var
n,m:integer;
begin
for n:=0 to StringGrid1.RowCount-1 do
for m:=0 to StringGrid1.ColCount-1 do
StringGrid1.Cells[m,n]:=IntToStr(n*StringGrid1.ColCount+m);
FFile:=CreateFile("StringGrid.grd",GENERIC_READ or GENERIC_WRITE,0,nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
SendGrid(FFile,StringGrid1);
Button2.Enabled:=true;
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
if FGrd<>nil then FGrd.Free;
SetFilePointer(FFile,0,nil,FILE_BEGIN);
FGrd:=GetGrid(FFile,Self);
CloseHandle(FFile);
Button2.Enabled:=false;
if FGrd <> nil then
begin
FGrd.Parent:=Self;
with StringGrid1 do FGrd.SetBounds(Left,Top+Height,Width,Height);
end;
end;
Тока для клиент-сервера это шибко неоптимально. Зато просто :)
Страницы: 1 вся ветка
Текущий архив: 2002.07.29;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.007 c