PDA

View Full Version : اندازه رکورد با زیرمجموعه هایی به صورت آرایه داینامیک



MEhdi Sobhani
یک شنبه 05 دی 1389, 12:01 عصر
با عرض سلام و خسته نباشید .
در برنامم یه رکورد تعریف کردم که زیر مجموعه های خودش شامل رکوردهای دیگه و آرایه های دینامیک از اعداد و رکوردهای دیگه و ... هستند .
می خواستم اون رو داخل فایل بریزم و از sizeof برای به دست آوردن طول این متغیر استفاده کردم ولی مشکلی که بود این بود که sizeof فقط اندازه خود رکورد و نه متغیر رو میداد . آیا راهی هست که بشه طول کامل متغیر رو به دست آورد و یه جا اون رو رویخت داخل فایل ؟
با تشکر فراوان .

vcldeveloper
یک شنبه 05 دی 1389, 13:50 عصر
نه، آرایه های دینامیک، اشیاء، و string ها به صورت pointer تعریف شدند. در نتیجه، وقتی با SizeOf اندازه رکورد را به دست میارید، فقط فضای اشغال شده برای pointer به ازاء هر کدام از اون فیلدها برگشت داده میشه. رکورد اطلاعی نداره که اون pointerها به چه چیزی در حافظه اشاره می کنند، و اون چیز حجمش چقدر هست. شما اگر میخواید اندازه دقیق داده را داشته باشید، باید اندازه رکورد را به دست بیارید، اندازه pointerهای مربوط به هر کدوم از اون فیلدهای خاص را از اندازه رکورد کسر کنید، سپس طول داده اشاره شده بوسیله هر کدام از اون فیلدهای خاص را به دست بیارید، و با اندازه رکورد جمع کنید.

MEhdi Sobhani
یک شنبه 05 دی 1389, 13:55 عصر
سلام
فرض کنید این نمونه کد هست :



Type1=record
x:integer;
end;
Type2=record
Y:array of X;
str:string;
end;
.
.
.
.
var
Temp1:Type2;
begin
setlength(temp1.y,100);
blockwrite(MyFile,Temp1,sizeOf(Temp1);



ممنون میشم اگر همین رو با یه مثال نشون بدید که چطور میشه کامل ریخت داخل فایل .
متشکر .

vcldeveloper
یک شنبه 05 دی 1389, 14:52 عصر
چطور میشه کامل ریخت داخل فایل .


type
Type1 = record
x: integer;
end;

Type2 = record
Y: array of Type1;
str: string;
end;

procedure SaveRecordToFile(ARec: Type2; const FileName: string);
var
FileStream : TFileStream;
Item: Type1;
BlockSize : Integer;
begin
FileStream := TFileStream.Create(FileName, fmCreate);
try
BlockSize := Length(ARec.Y) * SizeOf(Integer);
FileStream.Write(BlockSize,SizeOf(Integer));
for Item in ARec.Y do
begin
FileStream.Write(Item.x, SizeOf(Item.x));
end;

BlockSize := Length(ARec.str) * SizeOf(Char);
FileStream.Write(BlockSize,SizeOf(Integer));
FileStream.Write(ARec.str[1],BlockSize);
finally
FileStream.Free;
end;
end;

procedure TestSaveRecordToFile;
var
Temp1: Type2;
i: integer;
begin
SetLength(Temp1.Y, 100);
for i := Low(Temp1.Y) to High(Temp1.Y) do
Temp1.Y[i].x := Random(100);
Temp1.str := 'This is a test';
SaveRecordToFile(Temp1,'D:\Test');
end;

در کد بالا، قبل از نوشتن هر یک از فیلدهای Type2، اندازه اون فیلد به بایت در فایل نوشته میشه، و سپس محتوای اون فیلد در فایل نوشته میشه.

MEhdi Sobhani
دوشنبه 13 دی 1389, 21:54 عصر
سلام
ممنون از راهنماییتون .
یه لایبری پیدا کردم به نام kblib که هر متغیری با هر پیچیدگی رو که بهش بدیم داخل استریم میریزه و بعد هم همون رو لود میکنه و اگر متغیر آرایه داینامیک هم داشته باشه اون رو دوباره میسازه .
این لینک دانلود هست که با فیلتر شکن میشه دانلود کرد .
http://code.google.com/p/kblib/

BORHAN TEC
دوشنبه 13 دی 1389, 23:27 عصر
چقدر جالب!!!
با این روش حتی می توان چند فایل مختلف را در یک فایل ریخت. مثل winrar و ... .

MEhdi Sobhani
دوشنبه 13 دی 1389, 23:30 عصر
چقدر جالب!!!
با این روش حتی می توان چند فایل مختلف را در یک فایل ریخت. مثل winrar و ... .
سلام
بله
تقریبا هر چیزی رو میشه ریخت داخل این .
برنامه خودم یه متغیر اصلی داشت که همه چی داخل اون بود ، یه قسمت آرایه بود که از روی یه فایل پر میشد و چند قسمت دیگه آرایه هایی که از جاهای دیگه پر میشدن . با این کار مثل هایبرنیت شدن ویندوز شد و خیلی راحت کل اون متغیر و میریزه تو فایل دفعه بعد دوباره می خونه .