![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
запись в файл [D5, WinXP]
TButton © (2005-07-19 15:03:00)Доброго времени суток, господа.
Давно не писАл (разучивал php, работал, вобщем не досуг было).
А вот сейчас пересматривал старые проекты и нашёл проект спрайтового движка (прога для тестирования скорости и сохранения/загрузки). Перекомпилял (старые екзешники вирусом поело), вроде бы работает. И работает исправно. Из праздного любопытства решил глянуть файл с сохранённым спрайтом (32х32х4) и ужаснулся увидев его размер. 521Кб! Не поверил. Вставил в код метода SaveToFile (см. ниже) счётчики записаных байтов. По счётчику получается всё правильно (4168б = 4+4+64+4096). Но файл всё равно получается монструозный. Решил просмотреть его в блокноте (я всегда смотрю в блокноте =)).
\x4test * PGA д}B D\x16Њ \x80Њ \x8 Ђ` & L8B D\x16Њ шЉB D\x16Њ \x1E МIA ь\x19Њ & ш\x15Њ \x6 J\x1F\x10џЂ‡ \xF Ђ & ь\x19Њ \x2 e\xF\x10Эcњ яяя N ”ЄC D\x16Њ \x8 d\x2 №\x1 \x1
\x14 Ђ\x1 \x4 N ”ЄC D\x16Њ \x8 Њ\x1 Q\x1 \x1 \x1
\x14 Ђ\x1 \x4 2 аPA ¤уC D\x16Њ \x1 \xC\x1BЊ \x10 \x10 \x1E „PA \x1 j р5B ђ\x1BЊ ё\x1BЊ \x4test * PGA д}B D\x16Њ \x80Њ \x8 Ђ` & L8B D\x16Њ шЉB D\x16Њ \x1E МIA ь\x19Њ & ш\x15Њ \x6 J\x1F\x10џЂ‡ \xF Ђ & ь\x19Њ \x2 e\xF\x10Эcњ яяя N ”ЄC D\x16Њ \x8 d\x2 №\x1 \x1
\x14 Ђ\x1 \x4 N ”ЄC D\x16Њ \x8 Њ\x1 Q\x1 \x1 \x1
\x14 Ђ\x1 \x4 2 аPA ¤уC D\x16Њ \x1 \xC\x1BЊ \x10 \x10 \x1E „PA \x1 j р5B ђ\x1BЊ ё\x1BЊ Ш\x1BЊ \x4test * PGA д}B D\x16Њ \x80Њ \x8 Ђ` & L8B D\x16Њ шЉB D\x16Њ \x1E МIA ь\x19Њ & ш\x15Њ \x6 J\x1F\x10џЂ‡ \xF Ђ & ь\x19Њ \x2 e\xF\x10Эcњ яяя N ”ЄC D\x16Њ \x8 d\x2 №\x1 \x1
\x14 Ђ\x1 \x4 N ”ЄC D\x16Њ \x8 Њ\x1 Q\x1 \x1 \x1
\x14 Ђ\x1 \x4 2 аPA ¤уC D\x16Њ \x1 \xC\x1BЊ \x10 \x10 \x1E „PA \x1 j р5B ђ\x1BЊ ё\x1BЊ Ш\x1BЊ М p‹\x14 яяяя D\x16Њ љ\x5/\x2* PGA ґoA (\x1BЊ \x80Њ `\x1BЊ \x8 Ђ` " МHA ФoA (\x1BЊ Р\x14Њ `\x1BЊ \x4 \x1E МIA фoA (\x1BЊ \x1AЊ `\x1BЊ \x16 D\x16Њ \x16 D\x16Њ \x12 ьНC ,[Њ tґD р\x10 м\x10 tґD ИKЊ Ш\x10 tґD ИKЊ Д\x10 TForm1 tґD ИKЊ °\x10 ђ\x4 ђ\x4 аeE рЏE tґD ИKЊ ”\x10 \x4\x1DЊ \x10 ђ\x4 ђ\x4 D\x16Њ D\x16Њ D\x16Њ \x1 ИKЊ tґD \x18\x10 rm1\x5Form1\x4Left\x3Г \x3Top\x2k\x5Width\x3ё\x2\x6Height\x3а\x1\x7Caption\x6\x5Form1\x5Color\x7 clBtnFace\xCFont.Charset\x7\xFRUSSIAN_CHARSET
Font.Color\x7\xCclWindowText\xBFont.Height\x2х Font.Name\x6\x6Tahoma
Font.Style\xB\x6fsBold \xEOldCreateOrder\x8\x8OnCreate\x7
FormCreate
PixelsPerInch\x2`
TextHeight\x2
\x6TLabel\x6Label1\x4Left\x2\x8\x3Top\x2\x8\x5Width\x2"\x6Height\x2
\x7Caption\x6\x7::LOG:: \x6TLabel\x6Label2\x4Left\x3(\x1\x3Top\x2\x8\x5Width\x2`\x6Height\x2
\x7Caption\x6\x11Test length (sec) TPaintBox PaintBox1\x4Left\x2\x8\x3Top\x3А \x5Width\x2i\x6Height\x2i \x5TMemo\x5Memo1\x4Left\x2\x8\x3Top\x2\x18\x5Width\x3\x19\x1\x6Height\x3Ѓ \x5Ctl3D\x8
Lines.Strings\x1\x6\x5Memo1 \xBParentCtl3D\x8\x8ReadOnly
ScrollBars\x7
ssVertical\x8TabOrder\x2 TComboBox ComboBox1\x4Left\x3(\x1\x3Top\x2\x18\x5Width\x3‘ \x6Height\x3Ѓ \x5Style\x7\x8csSimple\x5Ctl3D\x8
ItemHeight\x2
\xBParentCtl3D\x8\x8TabOrder\x2\x1\x4Text\x6\x11
Items.Strings\x1\x6\x11\x6\x12\x6\x13\x6\x14\x6\x15\x6\x16\x6\x17\x6\x18\x6\x19\x6\x210\x6\x215\x6\x220 \x7TButton\x7Button1\x4Left\x2\x8\x3Top\x3 \x5Width\x2K\x6Height\x2\x19\x7Caption\x6 ::Start::\x8TabOrder\x2\x2\x7OnClick\x7\xCButton1Click \x7TButton\x7Button2\x4Left\x2X\x3Top\x3 \x5Width\x2K\x6Height\x2\x19\x7Caption\x6\x8::STOP::\x7Enabled\x8\x8TabOrder\x2\x3\x7OnClick\x7\xCButton2Click \x7TButton\x7Button3\x4Left\x3ш \x3Top\x3\x10\x1\x5Width\x2K\x6Height\x2\x19\x7Caption\x6\x7Button3\x8TabOrder\x2\x4\x7OnClick\x7\xCButton3Click \x7TButton\x7Button4\x4Left\x3ш \x3Top\x38\x1\x5Width\x2K\x6Height\x2\x19\x7Caption\x6\x7Button4\x8TabOrder\x2\x5\x7OnClick\x7\xCButton4Click
...
это (см. выше) вообще не моё!
моя прога этого не писала!
(точнее - не должна была писать)
очень похоже на dfm'ку
но её просто не должно там быть!
вот сижу и пытаюсь понять, что именно у меня в коде не правильно
для полной ясности привожу код
TRGBA (декларация)
TRGBA = record
r, g, b, a: byte;
end;
TRGBASprite (декларация)
TRGBASprite = object
pixels: array of TRGBA;
height, width: integer;
name: string[64];
procedure LoadFromFile(filename: string);
procedure SaveToFile(filename: string);
end;
TGE = object
private
public
function AddMix(c1,c2: TRGBA): TRGBA;
function BlendMix(c1,c2: TRGBA): TRGBA;
function MultMix(col: TRGBA; coef: byte): TRGBA;
end;
TRGBASprite.SaveToFile
procedure TRGBASprite.SaveToFile(filename: string);
var
f: file;
i: integer;
t, a: integer;
begin
AssignFile(f, filename);
Rewrite(f);
t:=0;
BlockWrite(f, height, SizeOf(integer), a);
t:=a;
BlockWrite(f, width, SizeOf(integer), a);
t:=t+a;
BlockWrite(f, name, 64, a);
t:=t+a;
ShowMessage(IntToStr(t));
for i:=0 to (height*width-1) do
begin
BlockWrite(f, pixels[i].r, 1, a);
t:=t+a;
BlockWrite(f, pixels[i].g, 1, a);
t:=t+a;
BlockWrite(f, pixels[i].b, 1, a);
t:=t+a;
BlockWrite(f, pixels[i].a, 1, a);
t:=t+a;
end;
ShowMessage(IntToStr(t));
CloseFile(f);
end;
Примечание:Курсивом выделены участки кода отвечающие за сбор информации о количестве записаных байтов.
MainUnit.pas (код для тестирования сохранения/загрузки)
procedure TMainForm.Button3Click(Sender: TObject);
var
i: integer;
begin
sp.height:=32;
sp.width:=32;
sp.name:='test';
SetLength(sp.pixels, 1024);
for i:=0 to 1023 do
sp.pixels[i]:=RandomColor;
sp.SaveToFile('c:\test.spt');
dr;
end;
procedure TMainForm.Dr;
var
i, j, n: integer;
begin
for i:=0 to sp.height-1 do
for j:=0 to sp.width-1 do
begin
n:=i*sp.width+j;
paintbox1.Canvas.Pixels[i,j]:=rgb(sp.pixels[n].r, sp.pixels[n].g, sp.pixels[n].b);
end;
end;
Примечание:sp: TRGBASPrite;
RandomColor - функция возвращающая случайный цвет в формате RGBA (TRGBA)
Как видно из кода метода TRGBASprite.SaveToFile
После последнего сообщения (4186) файл закрывается...
Хотя к чему я это, ведь вся лабуда, которая мне и не нужна вовсе вклинивается не то перед заголовком, не то между заголовком и телом.
Вобщем, надежда только на помощь из вне.
WBR, Marcuch
TButton (2005-07-22 04:40:00) [1]
> А где код?
а уже поправил =)
> Дык... в общем-то, в [4] уже переписано.
а я сам =)
всё равно собирался переписывать
> > TButton © (21.07.05 08:18) [7]
> > прочитал про packed
> > понял только то
>
>
> при таком подходе
а там больше ничего и не написано
не я конечно могу добавить, что понял, что "By default, the values in a structured type are aligned on word or double-word boundaries for faster access. When you declare a structured type, you can include the reserved word packed to implement compressed data storage."
но суть то заключается как раз в изменении соотношения размер/скорость
в данном конкретном случае, размер занимаемой памяти не так критичен, как скорость обращения к элементам массива.
Digitman (2005-07-21 13:46:00) [2]
> TButton © (21.07.05 08:18) [7]
> прочитал про packed
> понял только то
при таком подходе (читал и ни шута не понял) плюнь на packed или не packed - оно тебе индифферентно
либо, если плевать таки не хочется, возьми и раз и на всегда разберись, как и при каких реальныхусловиях та или иная структура (упакованая или неупакованая) будет влиять на размер исп.кода приложения и на сквозную производительность твоего алгоритма.
begin...end (2005-07-21 12:53:00) [3]> TButton © (21.07.05 8:18) [7]
> прочитал про packed
> понял только то что эта директива оптимизируем
> занимаемое в памяти место, но при этом замедляет
> доступ... имхо, лучше скорость
Наше дело -- предложить, Ваше дело -- отказаться.
> а нельзя указать не Pixels[0], а просто Pixels это же
> вроде бы и есть указатель на начало массива
Нельзя. Хотя Pixels -- это действительно указатель на начало массива. Поэтому и нельзя. Pixels -- это УКАЗАТЕЛЬ на начало массива, а Pixels[0] -- это САМО начало массива.
> сохранение работает как часы
> а загрузка почему-то вызывает AV =)
А где код?
> сейчас попробую переписать на файловые потоки
Дык... в общем-то, в [4] уже переписано.
TButton (2005-07-21 08:18:00) [4]прочитал про packed
понял только то что эта директива оптимизируем занимаемое в памяти место, но при этом замедляет доступ... имхо, лучше скорость
> Ну и что?
ну и я тогда (как в принципе и сейчас) частенько использовал примитивные методы, вроде того что приведён в примере. пусть он и незначительно проигрывает по скорости, но зато он легко воспринимается при чтении и надёжен.
> TStream.Write записывает Count байт из памяти, начиная с
> адреса переменной Buffer
теперь понял. а нельзя указать не Pixels[0], а просто Pixels это же вроде бы и есть указатель на начало массива.
попробовал исправить код
(rewrite(f, 1); и reset(f, 1);)
сохранение работает как часы
а загрузка почему-то вызывает AV =)
сам удивляюсь
грузится.
всё нормально грузится
и AV
бред какой-то
сейчас попробую переписать на файловые потоки
ПыСы
> имя (20.07.05 18:55) [3]
затрудняюсь даже представить, что это было =)
begin...end (2005-07-20 20:16:00) [5]> TButton © (20.07.05 19:49) [5]
>> в файл записывается не вся строка TRGBASprite.name
> почему?
Потому что строка типа string[6 4] занимает в памяти 6 5байт. 64 -- для символов, и ещё один (в начале) -- для хранения длины строки. В приведённом коде [0] в файл записывается только 64 байта строки. Лучше не указывать размер явно (потому что, во-первых, можно ошибиться, а во-вторых, когда-нибудь может понадобиться поменять размер строки), а использовать функцию sizeof, что и сделано в [4]. Разумеется, так можно записывать только короткие строки. Тела длинных строк (AnsiString) так записать не удастся.
>> Непонятно также, зачем ТАК записывать динамический
>> массив,
> я же говорю, проект старый
Ну и что?
> с packet record не знаком абсолютно
В принципе, в данном случае packed не обязательно. Но желательно, потому что сохранение и загрузка данных могут производиться при различных директивах выравнивания. Если и при записи, и при чтении выравнивание одно и то же -- packed можно убрать. Но при этом, возможно, увеличится размер файла.
> не совсем понятно, почему Pixels[0]?
Write(const Buffer; Count: Longint): Longint
TStream.Write записывает Count байт из памяти, начиная с адреса переменной Buffer. Чтобы записать динамический массив, передаём в качестве параметров нулевой элемент массива (ведь массив нужно записать весь, с самого начала, т.е. начиная с адреса нулевого элемента) и размер массива (в байтах).
TButton (2005-07-20 19:49:00) [6]
> Вы не указали явно размер записи файла.
всё. вспомнил.
> в файл записывается не вся строка TRGBASprite.name
почему?
> Непонятно также, зачем ТАК записывать динамический массив,
я же говорю, проект старый
по примеру
1) с packet record не знаком абсолютно
посмотрю в хелпе
2) > Write(Pixels[0], Height * Width * sizeof(Pixels[0]))
не совсем понятно, почему Pixels[0]?
ну и конечно же спасибо, за подсказки
begin...end (2005-07-20 19:09:00) [7]> TButton
Вот пример (хотя и не самый лучший) реализации SaveToFile/LoadFromFile с помощью файловых потоков.
Внимание! Измените объявление типа TRGBA: recordзамените на packed record.
procedure TRGBASprite.SaveToFile(const FileName: string);
begin
with TFileStream.Create(FileName, fmCreate) do
try
Write(Height, sizeof(Height));
Write(Width, sizeof(Width));
Write(Name, sizeof(Name));
Write(Pixels[0], Height * Width * sizeof(Pixels[0]))
finally
Free
end
end;
procedure TRGBASprite.LoadFromFile(const FileName: string);
begin
with TFileStream.Create(FileName, fmOpenRead) do
try
Read(Height, sizeof(Height));
Read(Width, sizeof(Width));
Read(Name, sizeof(Name));
SetLength(Pixels, Height * Width);
Read(Pixels[0], Height * Width * sizeof(Pixels[0]))
finally
Free
end
end.
(2005-07-20 18:55:00) [8]Удалено модератором
begin...end (2005-07-20 18:32:00) [9]> TButton © (19.07.05 15:03)
Проблема в том, что при вызове Rewrite (для нетипизированного файла) Вы не указали явно размер записифайла. По умолчанию же этот размер равен 128 байт (см. справку по Rewrite). Значение, возвращаемое процедурой BlockWrite в параметре AmtTransferred -- это количество записей, помещённых в файл. Т.к. отладка показала, что количество записей равно 4186, а размер одной записи равен 128 байтам, то размер файла будет 4186 * 128 = 535808 байт. Так что -- ничего удивительного. Чтобы исправить это, замените строкуRewrite(f)наRewrite(f, 1).
Есть и ещё ошибка -- в файл записывается не вся строка TRGBASprite.name. Непонятно также, зачем ТАК записывать динамический массив, ведь его можно записать одной строчкой кода.
TButton (2005-07-20 18:06:00) [10]однако вопрос потерялся...
была мысль использовать файловые потоки. это раз.
ещё мысль использовать file of byte
а не байтовые переменные разбирать и собирать в ручную.
но это бред.
надо будет попробовать первый вариант.