Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.03.12;
Скачать: [xml.tar.bz2];

Вниз

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

 
Дмитрий_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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.014 c
15-1139950401
AlterEgo of WondeRu
2006-02-14 23:53
2006.03.12
А в вашем регионе GPRS от Beeline работает?


15-1140181758
oldman
2006-02-17 16:09
2006.03.12
Умер Андрей Петров...


2-1141027882
veb
2006-02-27 11:11
2006.03.12
Delphi.NET


15-1140406651
никак не получается
2006-02-20 06:37
2006.03.12
таблицы


15-1139941005
Кто - то
2006-02-14 21:16
2006.03.12
Вопрос законопослушного программиста





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский