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

Вниз

запись в файл   Найти похожие ветки 

 
TButton ©   (2005-07-19 15:03) [0]

Доброго времени суток, господа.
Давно не писАл (разучивал php, работал, вобщем не досуг было).
А вот сейчас пересматривал старые проекты и нашёл проект спрайтового движка (прога для тестирования скорости и сохранения/загрузки). Перекомпилял (старые екзешники вирусом поело), вроде бы работает. И работает исправно. Из праздного любопытства решил глянуть файл с сохранённым спрайтом (32х32х4) и ужаснулся увидев его размер. 521Кб! Не поверил. Вставил в код метода SaveToFile (см. ниже) счётчики записаных байтов. По счётчику получается всё правильно (4168б = 4+4+64+4096). Но файл всё равно получается монструозный. Решил просмотреть его в блокноте (я всегда смотрю в блокноте =)).

       test                                                                       *   PGA     д}B DЊ 0Њ       Ђ`       &   L8B DЊ                 шЉB DЊ    МIA             ьЊ     &   шЊ    JџЂ‡        Ђ        &   ьЊ    eЭcњ      яяя         N   ”ЄC DЊ  d    №            
        Ђ                          N   ”ЄC DЊ  Њ    Q           
        Ђ                          2   аPA     ¤уC DЊ                 Њ          „PA                    j   р5B         ђЊ ёЊ     test                                                                       *   PGA     д}B DЊ 0Њ       Ђ`       &   L8B DЊ                 шЉB DЊ    МIA             ьЊ     &   шЊ    JџЂ‡        Ђ        &   ьЊ    eЭcњ      яяя         N   ”ЄC DЊ  d    №            
        Ђ                          N   ”ЄC DЊ  Њ    Q           
        Ђ                          2   аPA     ¤уC DЊ                 Њ          „PA                    j   р5B         ђЊ ёЊ ШЊ test                                                                       *   PGA     д}B DЊ 0Њ       Ђ`       &   L8B DЊ                 шЉB DЊ    МIA             ьЊ     &   шЊ    JџЂ‡        Ђ        &   ьЊ    eЭcњ      яяя         N   ”ЄC DЊ  d    №            
        Ђ                          N   ”ЄC DЊ  Њ    Q           
        Ђ                          2   аPA     ¤уC DЊ                 Њ          „PA                    j   р5B         ђЊ ёЊ ШЊ           М                     p‹ яяяя                        DЊ     љ/*   PGA     ґoA (Њ 0Њ `Њ   Ђ`       "   МHA     ФoA (Њ РЊ `Њ       МIA     фoA (Њ  Њ `Њ    DЊ                DЊ                        ьНC ,[Њ tґD р  м          tґD ИKЊ Ш          tґD ИKЊ Д  TForm1  tґD ИKЊ °  ђ  ђ  аeE рЏE tґD ИKЊ ”  Њ    ђ  ђ  DЊ DЊ         DЊ                                                                            ИKЊ tґD   rm1Form1LeftГ TopkWidthёHeightаCaptionForm1Color clBtnFace Font.CharsetRUSSIAN_CHARSET
Font.Color clWindowText Font.Heightх Font.NameTahoma
Font.Style fsBold OldCreateOrderOnCreate
FormCreate
PixelsPerInch`
TextHeight
TLabelLabel1LeftTopWidth"Height
Caption::LOG::  TLabelLabel2Left(TopWidth`Height
CaptionTest length (sec)   TPaintBox PaintBox1LeftTopА WidthiHeighti  TMemoMemo1LeftTopWidthHeightЃ Ctl3D
Lines.StringsMemo1 ParentCtl3DReadOnly
ScrollBars
ssVerticalTabOrder    TComboBox ComboBox1Left(TopWidth‘ HeightЃ StylecsSimpleCtl3D
ItemHeight
ParentCtl3DTabOrderText1
Items.Strings123456789101520   TButtonButton1LeftTop  WidthKHeightCaption ::Start::TabOrderOnClick Button1Click  TButtonButton2LeftXTop  WidthKHeightCaption::STOP::EnabledTabOrderOnClick Button2Click  TButtonButton3Leftш TopWidthKHeightCaptionButton3TabOrderOnClick Button3Click  TButtonButton4Leftш Top8WidthKHeightCaptionButton4TabOrderOnClick Button4Click        
...

это (см. выше) вообще не моё!
моя прога этого не писала!
(точнее - не должна была писать)
очень похоже на 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-20 18:06) [1]

однако вопрос потерялся...
была мысль использовать файловые потоки. это раз.
ещё мысль использовать file of byte
а не байтовые переменные разбирать и собирать в ручную.
но это бред.
надо будет попробовать первый вариант.


 
begin...end ©   (2005-07-20 18:32) [2]

> TButton ©   (19.07.05 15:03)

Проблема в том, что при вызове Rewrite (для нетипизированного файла) Вы не указали явно размер записи файла. По умолчанию же этот размер равен 128 байт (см. справку по Rewrite). Значение, возвращаемое процедурой BlockWrite в параметре AmtTransferred -- это количество записей, помещённых в файл. Т.к. отладка показала, что количество записей равно 4186, а размер одной записи равен 128 байтам, то размер файла будет 4186 * 128 = 535808 байт. Так что -- ничего удивительного. Чтобы исправить это, замените строку Rewrite(f) на Rewrite(f, 1).

Есть и ещё ошибка -- в файл записывается не вся строка TRGBASprite.name. Непонятно также, зачем ТАК записывать динамический массив, ведь его можно записать одной строчкой кода.


 
имя   (2005-07-20 18:55) [3]

Удалено модератором


 
begin...end ©   (2005-07-20 19:09) [4]

> 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.


 
TButton ©   (2005-07-20 19:49) [5]


> Вы не указали явно размер записи файла.

всё. вспомнил.

>  в файл записывается не вся строка TRGBASprite.name

почему?

> Непонятно также, зачем ТАК записывать динамический массив,

я же говорю, проект старый

по примеру
1) с packet record не знаком абсолютно
посмотрю в хелпе
2) > Write(Pixels[0], Height * Width * sizeof(Pixels[0]))
не совсем понятно, почему Pixels[0]?

ну и конечно же спасибо, за подсказки


 
begin...end ©   (2005-07-20 20:16) [6]

> TButton ©   (20.07.05 19:49) [5]

>>  в файл записывается не вся строка TRGBASprite.name
> почему?

Потому что строка типа string[64] занимает в памяти 65 байт. 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-21 08:18) [7]

прочитал про 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-21 12:53) [8]

> TButton ©   (21.07.05 8:18) [7]

> прочитал про packed
> понял только то что эта директива оптимизируем
> занимаемое в памяти место, но при этом замедляет
> доступ... имхо, лучше скорость

Наше дело -- предложить, Ваше дело -- отказаться.

> а нельзя указать не Pixels[0], а просто Pixels это же
> вроде бы и есть указатель на начало массива

Нельзя. Хотя Pixels -- это действительно указатель на начало массива. Поэтому и нельзя. Pixels -- это УКАЗАТЕЛЬ на начало массива, а Pixels[0] -- это САМО начало массива.

> сохранение работает как часы
> а загрузка почему-то вызывает AV =)

А где код?

> сейчас попробую переписать на файловые потоки

Дык... в общем-то, в [4] уже переписано.


 
Digitman ©   (2005-07-21 13:46) [9]


> TButton ©   (21.07.05 08:18) [7]
> прочитал про packed
> понял только то


при таком подходе (читал и ни шута не понял) плюнь на packed или не packed - оно тебе индифферентно

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


 
TButton ©   (2005-07-22 04:40) [10]


> А где код?

а уже поправил =)

> Дык... в общем-то, в [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."

но суть то заключается как раз в изменении соотношения размер/скорость

в данном конкретном случае, размер занимаемой памяти не так критичен, как скорость обращения к элементам массива.



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

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

Наверх




Память: 0.53 MB
Время: 0.044 c
1-1121687965
Caridi
2005-07-18 15:59
2005.08.07
задать условие MaskEdit1.Text


14-1121273216
TBender
2005-07-13 20:46
2005.08.07
IRC...


1-1121591340
Чайничек
2005-07-17 13:09
2005.08.07
Удаление в файле


3-1120361092
serguncho
2005-07-03 07:24
2005.08.07
Проблема с представление информации в Firebird


1-1121867379
Dust
2005-07-20 17:49
2005.08.07
Опять вопрос про качественный код: