Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.03.12;
Скачать: CL | DM;

Вниз

Как лучше хранить координаты точек в файле?   Найти похожие ветки 

 
Дмитрий_177   (2006-02-21 21:19) [0]

Как лучше хранить координаты точек в файле? У меня есть много точек с координатами (x, y), как лучше всего сохранять их в файле?


 
Zeqfreed ©   (2006-02-21 21:31) [1]

Полагаю, двойками целочисленных значений фиксированного размера.


 
Дмитрий_177   (2006-02-21 21:39) [2]

а как это? я сначала думал так: два текстовых вайла... в одном x-ы, в другом y-ки.. и первая строка одного и второго файла и будут координаты... но тут 2-а файла и строку переводить из string в integer... это на скорости мне кажется скажется...


 
Джо ©   (2006-02-21 21:45) [3]

Можно в типизированных файлах (file of TPoint), можно не типизированных (file). Да как угодно можно.


 
Джо ©   (2006-02-21 21:46) [4]

У тебя точки в какой структуре данных хранятся?


 
Дмитрий_177   (2006-02-21 21:49) [5]

еще пока никак.... я их из bmp файла считываю... т.е. определенным цветом точки... чтобы каждый раз не тратить время напоиск этих точек определенным каким-то цветом, я хочу их как-то сохранить...


 
Дмитрий_177   (2006-02-21 22:08) [6]

А ктонибудь знает модуль DataFile? я им пользуюсь и сохраняю все... это как ini-файлы только лучше


 
Джо ©   (2006-02-21 22:29) [7]

> [5] Дмитрий_177   (21.02.06 21:49)
> еще пока никак.... я их из bmp файла считываю

Куда?


 
Zeqfreed ©   (2006-02-21 22:35) [8]


type
 TDynPointsArray = array of TPoint;

. . .

function SavePoints(const Filename : String; const Points : array of TPoint) : Boolean;
type
 TPointsArray = array[0..0] of TPoint;
var
 f, i : Integer;
 buf : Pointer;
begin
 Result := false;

 f := FileCreate(Filename, fmCreate);
 if (f = -1) then Exit;
  GetMem(buf, SizeOf(TPoint) * Length(Points));
  try
   for i := Low(Points) to High(Points) do
    TPointsArray(buf^)[i] := Points[i];

   FileWrite(f, buf^, SizeOf(TPoint) * Length(Points));
   Result := true;
  finally
   FreeMem(buf);
  end;
 try

 finally
  FileClose(f);
 end;
end;

function ReadPoints(const Filename : String; var Points : TDynPointsArray) : Boolean;
type
 TPointsArray = array[0..0] of TPoint;
var
 f, i, size : Integer;
 buf : Pointer;
begin
 Result := false;

 f := FileOpen(Filename, fmOpenRead or fmShareDenyWrite);
 if (f = -1) then Exit;

 try
  size := GetFileSize(f, nil);

  GetMem(buf, size);
  try
   if FileRead(f, buf^, size) = size then begin
    SetLength(Points, size div SizeOf(TPoint) + 1);

    for i := 0 to (size div SizeOf(TPoint)) do
     Points[i] := TPointsArray(buf^)[i];

    Result := true;
   end;
  finally
   FreeMem(buf);
  end;
 finally
  FileClose(f);
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 a, b : TDynPointsArray;
 i : Integer;
 s : String;
begin
 Randomize();

 SetLength(a, 2);
 for i := Low(a) to High(a) do begin
  a[i].X := Random(High(Integer));
  a[i].Y := Random(High(Integer));
 end;

 if SavePoints("C:\1.points", a) then
  if ReadPoints("C:\1.points", b) then begin
   for i := Low(a) to High(a) do begin
    s := s + Format("%d, %d"#13#10, [b[i].X, b[i].Y]);
   end;

   ShowMessage(s);
  end;
end;


 
Джо ©   (2006-02-21 23:13) [9]

Такое вроде по-проще будет ;)


unit PointsUtils;

interface
uses Windows, SysUtils, Classes;

type

 TPoints = class
 private
   FList: TList;
   procedure SetItems(Index: Integer; const Value: TPoint);
   function GetItems(Index: Integer): TPoint;
   function GetCount: Integer;
 public
   constructor Create();
   destructor Destroy; override;
   function Add (X,Y: Integer): Integer; overload;
   function Add (APoint: TPoint): Integer; overload;
   property Count: Integer read GetCount;
   property Items[Index: Integer]: TPoint read GetItems write SetItems; default;
   procedure Clear;
   procedure SaveToStream (AStream: TStream);
   procedure SaveToFile (AFileName: string);
   procedure LoadFromStream (AStream: TStream);
   procedure LoadFromFile (AFileName: string);
 end;

implementation

type
 PPoint = ^TPoint;

{ TPoints }

function TPoints.Add(X, Y: Integer): Integer;
var
 Pt: TPoint;
begin
 Pt.X := X;
 Pt.Y := Y;
 Result := Add (Pt)
end;

function TPoints.Add(APoint: TPoint): Integer;
var
 NewPt: PPoint;
begin
 GetMem (NewPt,SizeOf(TPoint));
 NewPt^ := APoint;
 Result := FList.Add(NewPt)
end;

procedure TPoints.Clear;
var
 I: Integer;
begin
 for I := Count - 1 downto 0 do
   FreeMem (FList[I]);
 FList.Clear;
end;

constructor TPoints.Create;
begin
 inherited;
 FList := TList.Create;
end;

destructor TPoints.Destroy;
begin
 Clear;
 FList.Free;
 inherited;
end;

function TPoints.GetCount: Integer;
begin
 Result := FList.Count
end;

function TPoints.GetItems(Index: Integer): TPoint;
begin
 Result := PPoint(FList[Index])^
end;

procedure TPoints.LoadFromFile(AFileName: string);
var
 Fs: TFileStream;
begin
 Fs := TFileStream.Create(AFileName,fmOpenRead);
 try
   LoadFromStream(Fs);
 finally
   Fs.Free;
 end;
end;

procedure TPoints.LoadFromStream(AStream: TStream);
var
 I,
 Cnt: Integer;
 Pt: TPoint;
begin
 Clear;
 AStream.Read(Cnt,SizeOf(Cnt));
 for I := 0 to Cnt-1 do
 begin
   AStream.Read(Pt,SizeOf(Pt));
   Add (Pt)
 end;
end;

procedure TPoints.SaveToFile(AFileName: string);
var
 Fs: TFileStream;
begin
 Fs := TFileStream.Create(AFileName,fmCreate);
 try
   SaveToStream(Fs);
 finally
   Fs.Free;
 end;
end;

procedure TPoints.SaveToStream(AStream: TStream);
var
 I: Integer;
 Pt: TPoint;
 Cnt: Integer;
begin
 // количество точек
 Cnt := Count;
 AStream.Write(Cnt,SizeOf(Cnt));

 // сами точки
 for I := 0 to Count - 1 do
 begin
   Pt := Self[I];
   AStream.Write(Pt,SizeOf(TPoint));
 end;
end;

procedure TPoints.SetItems(Index: Integer; const Value: TPoint);
begin
 PPoint(FList[Index])^ := Value
end;

end.


Пример использования:
---------------------

procedure TForm18.Button1Click(Sender: TObject);
var
 APoints: TPoints;
 I: Integer;
begin
 APoints := TPoints.Create;
 try

   APoints.Add(10,20);
   APoints.Add(30,40);
   APoints.Add(50,60);

   APoints.SaveToFile("d:\points.dat");
   
   APoints.Clear;

   APoints.LoadFromFile ("d:\points.dat");
   for I := 0 to APoints.Count - 1 do
     ShowMessageFmt("%d,%d",[APoints[I].X,APoints[I].Y]);
     
 finally
   APoints.Free;
 end;
end;


 
Zeqfreed ©   (2006-02-21 23:37) [10]


> Такое вроде по-проще будет ;)

Сложно сказать наверняка :)
Было бы больше пользы, конечно, если бы автор ещё свой вариант составил.


 
Дмитрий_177   (2006-02-21 23:54) [11]

Я вот разбираюсь... хочу написать еще две функции в DataFile, какраз для считывания точек... но что-то никак... если кто не знает могу скинуть модуль, мне он нравится )))


 
Дмитрий_177   (2006-02-21 23:55) [12]

в этих примерах при чтении из файла мы знаем что ф этом файле только точки... а вдруг там еще чтонибудь будет записано?


 
Джо ©   (2006-02-22 00:01) [13]

> [12] Дмитрий_177   (21.02.06 23:55)
> в этих примерах при чтении из файла мы знаем что ф этом
> файле только точки... а вдруг там еще чтонибудь будет записано?

Что значит "вдруг"?


 
Дмитрий_177   (2006-02-22 00:11) [14]

как в ini-файлах.. и строки и числа и др. т.е. не только точки...


 
Дмитрий_177   (2006-02-22 00:12) [15]

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


 
Джо ©   (2006-02-22 00:19) [16]

Смотри класс TIniFile и его методы WriteInteger и ReadInteger.


 
Дмитрий_177   (2006-02-22 00:22) [17]

да, но там же вроде как фиксированный размер типа Integer, а тут массив из TPointer, как мне узнать длинну массива или как-то там еще, чтобы прочитать его


 
Джо ©   (2006-02-22 00:29) [18]

> , как мне узнать длинну массива

High


 
Дмитрий_177   (2006-02-22 00:36) [19]

у меня что-то не получается (((

функции из DataFile для чтения и записи данных

function TDataFile.WriteData(Section, Ident: string; pBuf: Pointer; Count: Integer): Integer;
var
 Hdr : IDataHeader;
 P   : Pointer;
begin
 Delete(Section, Ident);
 FFile.Seek(0, soFromEnd);
 { feel header }
 Hdr.Id := DF_HEADER_IDENT;
 StrPCopy(Hdr.Section, Section);
 StrPCopy(Hdr.Ident, Ident);
 Hdr.Size := Count;
 { xor }
 EncryptBuf(@Hdr, SizeOf(IDataHeader));
 { write header }
 Result := FFile.Write(Hdr, SizeOf(IDataHeader));
 if( Result > -1 )then
 begin
  GetMem(P, Count);
  try
   Move(pBuf^, P^, Count);
   { xor data }
   EncryptBuf(P, Count);
   { write data }
   Result := FFile.Write(P^, Count);
  finally
   FreeMem(P, Count);
  end;
 end;
end;

function TDataFile.ReadData(Section, Ident: string; pBuf: Pointer): Integer;
var
 Found   : boolean;
 Hdr     : IDataHeader;
begin
 Found := FindIdent(Section, Ident, @Hdr);
 if( Found  )then
 begin
  Result := FFile.Read(pBuf^, Hdr.Size);
  DecryptBuf(pBuf, Hdr.Size);
 end else
  Result := -1;
end;


программа:

type
TDynPointsArray = array of TPoint;

procedure TForm1.Button1Click(Sender: TObject);  // запись
var
 a: TDynPointsArray;
 i: integer;
begin
SetLength(a, 2);
for i := Low(a) to High(a) do
 begin
 a[i].X := Random(500);
 a[i].Y := Random(500);
 end;

with TDataFile.Create("C:\1.points") do
 try
 WriteData("1", "1", @a,  SizeOf(TPoint) * Length(a));

 finally
 Free;
 end;
end;

procedure TForm1.Button2Click(Sender: TObject);   // чтение
var
 Buf: array[0..1023]of Char;
 a: TDynPointsArray;
 i, Count: integer;
 s: string;
begin
with TDataFile.Create("C:\1.points") do
 try
 Count := ReadData("1", "1", @Buf);
 if (Count >= SizeOf(TPoint)) then
   Move(Buf, a, SizeOf(TPoint));

 finally
 Free;
 end;

for i := Low(a) to High(a) do
 begin
 s := s + IntToStr(a[i].X) + " " + IntToStr(a[i].Y) + "   ";
 end;

ShowMessage(s);
end;


 
Дмитрий_177   (2006-02-22 15:37) [20]

я наверно поздно вопрос задал и с появлением новых он затерялся...


 
Дмитрий_177   (2006-02-24 23:42) [21]

А можно ли такой массив перевести в поток? там есть функция WriteStream, сохраняющая поток...


 
Дмитрий_177   (2006-02-24 23:43) [22]

но потом обратно конечно... из потока в массив для чтения )))


 
TStas ©   (2006-02-24 23:50) [23]

Если координаты - TPoint, то FIle of TPOint Я, например, только TFIleStream"Ом и пользуюсь В нем замечательно храняться ЛЮБЫЕ структуры. Sz:=fs.Seek(0, soFromEnd) даст вам размер вашего файла в байтах, дальше, думаю, понятно


 
Дмитрий_177   (2006-02-24 23:53) [24]

TStas © вы не поняли... у меня в одном файле не только точки хранятся... но и числа там разные, и всякая другая информация...


 
Zeqfreed ©   (2006-02-24 23:58) [25]

23] TStas ©   (24.02.06 23:50)

> Sz:=fs.Seek(0, soFromEnd) даст вам размер вашего файла в
> байтах

Согласно справке, Seek изменит текущую позицию в потоковом ресурсе. А вот TFileStream.Size как раз вернет размер файла.

[24] Дмитрий_177   (24.02.06 23:53)

> у меня в одном файле не только точки хранятся... но и числа
> там разные, и всякая другая информация...

Нужно использовать нетипизированные файлы. А для хранения числовых данных использование текстовых файлов, а тем более каких-то ini-подобных оберток, как мне кажется, жутко неудобно.


 
Джо ©   (2006-02-25 00:17) [26]

> [24] Дмитрий_177   (24.02.06 23:53)
> у меня в одном файле не только точки
> хранятся... но и числа там разные, и всякая другая информация...

Тут уже советов надавали — море. На все случаи жизни. А ты все повторяешь одно и тоже, вероятно, не дав себе труда хотя бы понять то, что тебе писали.


 
TStas ©   (2006-02-25 00:35) [27]

А как раз понял, почему TFileStream и посоветовал У меня в нем хранилась элекктронная таблица, наподобие экселевской, с форматированием, текстом и формулой произвольной длинны, нй и координатами, конечно.


 
Джо ©   (2006-02-25 00:38) [28]

> [27] TStas ©   (25.02.06 00:35)
> А как раз понял, почему TFileStream и посоветовал

И правильно, кстати, посоветовал. :)


 
Дмитрий_177   (2006-02-25 00:42) [29]

а как мне перевести массив в поток? какой функцией? подскажите пожалуйста


 
Дмитрий_177   (2006-02-25 00:43) [30]

ну или не только массив... вообще любую переменную или класс... TStas © как вы перевели таблицу в поток?


 
Джо ©   (2006-02-25 00:44) [31]

>
>
> [29] Дмитрий_177   (25.02.06 00:42)
> а как мне перевести массив в поток? какой функцией? подскажите
> пожалуйста

Ты читал посты: [8] и [9]? Разбирался с ними? Какие вопросы возникли в процессе разбора?
Там, между прочим, готовые рабочие примеры были...


 
Дмитрий_177   (2006-02-25 00:52) [32]

блин... опять снова здорова.....((((((( но там же подразумевается что во всем файле будут храниться только точки и ничего больше... поетому мы можем написать эти строки при чтении из [8]:

size := GetFileSize(f, nil);
...

if FileRead(f, buf^, size) = size then begin
   SetLength(Points, size div SizeOf(TPoint) + 1);

т.е. работать с размером файла, неволнуясь ч в том что там еще что-то может храниться...

или я не правильно понимаю эти примеры?


 
Джо ©   (2006-02-25 01:02) [33]

> [32] Дмитрий_177   (25.02.06 00:52)
> но там же подразумевается
> что во всем файле будут храниться только точки и ничего
> больше...

Ничего такого там не подразумевается. Напротив, в моем примере сделано все, чтобы можно было легко расширить класс для хранения записи/чтения чего-угодно.


 
Джо ©   (2006-02-25 01:05) [34]

В поток что угодно записать можно. И прочитать.


 
Дмитрий_177   (2006-02-25 01:33) [35]

так... завтра начинаю все сначала читать про потоки и про файлы... спасибо, Джо, а то я не понимал сначала... и писал ерунду...)))


 
Дмитрий_177   (2006-02-27 15:51) [36]

Джо, я сейчас расширяю ваш класс для хранения в нем изображений еще... У меня вопрос в том, что функциям "Add" надо всегда "overload;" приписывать? это же вроде как для того чтобы переписать функцию... а если я функцию не "Add" а "AddPoint" назову? всеравно "overload;" писать?


 
Джо ©   (2006-02-27 16:01) [37]

> а если я функцию не "Add" а "AddPoint" назову? всеравно
> "overload;" писать?

Нет, конечно. Overload нужен для объявления методов с одинаковыми именами, имеющими разные параметры.


 
Дмитрий_177   (2006-02-27 16:30) [38]

спасибо ))) еще один технический вопросик... при использовании раньше подобных ini-оберткок, как сказал Zeqfreed, можно было например сразу считать изображение в какойнибудь компонент, например в кнопку, а тут считывается сразу все, и будет храниться в памяти... ведь так? и потом оттуда уже записываем в кнопку или еще там куда... я так это понимаю?



Страницы: 1 вся ветка

Текущий архив: 2006.03.12;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.063 c
11-1106741957
WhiteGuy
2005-01-26 15:19
2006.03.12
Замена строки


1-1139210575
MetalFan
2006-02-06 10:22
2006.03.12
проблема с кодировкой при копированиии в буфер


2-1140621520
mihauzen
2006-02-22 18:18
2006.03.12
Чем/как реализовать "многооконность" в одном приложении?


2-1140528763
DDS
2006-02-21 16:32
2006.03.12
Перемешивание!


3-1137783314
olevacho_
2006-01-20 21:55
2006.03.12
Ошибка cannot transliterate character between character sets