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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.037 c
14-1121321379
syte_ser78
2005-07-14 10:09
2005.08.07
Курение


6-1114747447
Valera
2005-04-29 08:04
2005.08.07
IdIcmpClient и многопоточность


4-1118130484
Андрей Жук
2005-06-07 11:48
2005.08.07
Как получить выбранный Item в ComboBoxEx


1-1121345438
dRake
2005-07-14 16:50
2005.08.07
Проблема с классами...


14-1121628347
Knight
2005-07-17 23:25
2005.08.07
Ремонт XP...





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский