Форум: "Основная";
Текущий архив: 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 clBtnFaceFont.CharsetRUSSIAN_CHARSET
Font.ColorclWindowTextFont.Heightх Font.NameTahoma
Font.StylefsBold 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::TabOrderOnClickButton1Click TButtonButton2LeftXTop WidthKHeightCaption::STOP::EnabledTabOrderOnClickButton2Click TButtonButton3Leftш TopWidthKHeightCaptionButton3TabOrderOnClickButton3Click TButtonButton4Leftш Top8WidthKHeightCaptionButton4TabOrderOnClickButton4Click
...
это (см. выше) вообще не моё!
моя прога этого не писала!
(точнее - не должна была писать)
очень похоже на 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