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

Вниз

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

 
SkyRanger ©   (2004-06-07 08:06) [0]

Решил я сделать что то вроде PAK-файла как в Квейке было в свое время.

Нашел статью с примером, правда на Си, но это не проблема.

Создал заголовок файла

TPkgFileHeader = record
 PkgSignature     : string[3];
 PkgVer           : Single;
 PkgNumberOfFiles : integer;
 PkgReserved      : string[128];
end;

И Динамический список для таблицы имен файлов, которые храняться внутри

PPkgFileTableItem = ^TPkgFileTableItem;
TPkgFileTableItem = record
 PkgFileName : string[100];
 PkgFileSize : integer;
 PkgOffset   : Integer;
 PkgNextItem : PPkgFileTableItem;
end;

Заполняю заголовок

PkgFileHeader.PkgSignature:="PKG";
PkgFileHeader.PkgVer:=1.0;
PkgFileHeader.PkgNumberOfFiles:=5;
for I:=1 to 128 do
PkgFileHeader.PkgReserved[I]:=" ";

Потом таблицу

FileListRoot:=nil;

New(FileListNew);
FileListNew^.PkgFileName:="file1.txt";
FileListNew^.PkgFileSize:=512;
FileListNew^.PkgOffset:=0;
FileListNew^.PkgNextItem:=nil;
FileListRoot:=FileListNew;
FileListCurr:=FileListNew;

New(FileListNew);
FileListNew^.PkgFileName:="file2.txt";
FileListNew^.PkgFileSize:=612;
FileListNew^.PkgOffset:=613;
FileListNew^.PkgNextItem:=nil;
FileListCurr^.PkgNextItem:=FileListNew;
FileListCurr:=FileListNew;

проверяю правильно ли запонил

FileListCurr:=FileListRoot;
while FileListCurr^.PkgNextItem<>nil do
begin
Memo1.Lines.Add("Check "+FileListCurr^.PkgFileName);
FileListCurr:=FileListCurr^.PkgNextItem;
end;
Memo1.Lines.Add("Check "+FileListCurr^.PkgFileName);

Открываю файл и начинаю писатьв него

AssignFile(F,"c:\pakfile.pkg");
Rewrite(F);

Сначало заголовок

BlockWrite(F,PkgFileHeader,1);

Тут и начинаются косяки. Откуда то берется символ с ASCII кодом 3
Хотя если я читаю обратно, то он нигде не проявляется... Но в Фаре точно виден он.

Дальше круче
Пишу таблицу в файлов в открытый файл

FileListCurr:=FileListRoot;

while FileListCurr^.PkgNextItem<>nil do
begin

BlockWrite(F,FileListCurr^.PkgFileName,1);
BlockWrite(F,FileListCurr^.PkgFileSize,1);
BlockWrite(F,FileListCurr^.PkgOffset,1);

Memo1.Lines.Add("Write "+FileListCurr^.PkgFileName);
FileListCurr:=FileListCurr^.PkgNextItem;
end;

BlockWrite(F,FileListCurr^.PkgFileName,1);
BlockWrite(F,FileListCurr^.PkgFileSize,1);
BlockWrite(F,FileListCurr^.PkgOffset,1);

Memo1.Lines.Add("Write "+FileListCurr^.PkgFileName);

CloseFile(F);

В результате после заголовка в файле получается поная чушь
первым символом пишется какойто ASCII с кодом 9 потом имя файла, потом какой то мусор причем повторяется заголовок файла...

У меня такое ощущение что я где то намутил и он записывает лишенее, но где понять не могу...

Как сделать чтобы все записывалось нормально и без мусора???


 
KilkennyCat ©   (2004-06-07 09:51) [1]


> PPkgFileTableItem = ^TPkgFileTableItem;
> TPkgFileTableItem = record
>  PkgFileName : string[100];
>  PkgFileSize : integer;
>  PkgOffset   : Integer;
>  PkgNextItem : PPkgFileTableItem;
> end;


не уверен, конечно, но что-то странно выглядит...


 
SkyRanger ©   (2004-06-07 10:49) [2]

Обыкновенное описание списка с указателе на след элемент...
Все работает! Че странного то???


 
KilkennyCat ©   (2004-06-07 11:08) [3]


> SkyRanger ©   (07.06.04 10:49) [2]


наверное... просто я редко так заумно пишу,все стараюсь попроще.
А на первый взгляд, рекурсия :)


 
wicked ©   (2004-06-07 11:13) [4]

странно не то... странно вот это:

> TPkgFileHeader = record
>  PkgSignature     : string[3];
>  PkgVer           : Single;
>  PkgNumberOfFiles : integer;
>  PkgReserved      : string[128];
> end;

символ к кодом #3 и будет там браться, поскольку формат хранения строк таков "<байт длины>байты строки"... т.е. если есть строка длиной 3 символа, то в памяти она займет 4 байта - байт длины плюс 3 байта на строку... если хотите избавиться от символа #3, выберите другой способ хранения, например, массивы символов....

а вообще то q3 хранит свои данные в непакованном zip-формате...


 
1008 ©   (2004-06-07 11:29) [5]

wicked ©  (07.06.04 11:13) [4]

а вообще то q3 хранит свои данные в непакованном zip-формате...

не подскажите как это понимать?
Компрессор zip использует алгоритм компрессии семейсвтва  LZ.


 
SkyRanger ©   (2004-06-07 11:31) [6]

Я имел первый в виду. За подсказку пасибо!
Заработало!

А вот откуда берется мусор во второй части???
причем этот мусор содержит инфу которая добавляется в Memo1

Check file1.txt
Check file2.txt
Write file1.txt
Write file1.txt

Check file1.txt
Check file2.txt
Write file1.txt
Write file1.txt
Привблизительное содержание, перемешаное с разными символами

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


 
SkyRanger ©   (2004-06-07 11:45) [7]

Интересно как то получется
В файле под каждый блок выделяется по 112 байт
Немного помогло обнуление
for I:=1 to 128 do
FileListNew^.PkgFileName[I]:=" ";
Но все равно в конце файла получается дофига всякого мусора


 
SkyRanger ©   (2004-06-07 13:06) [8]

В принципе я понял в чем дело, похоже когда происходит запись в файл из FileListNew^.PkgFileName то вместо того чтобы записать в файл просто значение по этому адресу, ведь разыменование правильно вроде происходит, так вот она записывает все что есть в памяти начиная с этого адреса.
Хотя теоретически такого быть не должно...
И как с этим бороться???


 
Erik1   (2004-06-07 13:11) [9]

А почему бы несделать формат с фиксированой длиной блока? Тогда и указатель непонадовится на следующий блок. Кроме того обнуляют точно не циклом! FillChar(var X; Count: Integer; Value: Byte)
Еще стоит использовать packed record тогда небудет выравнивания. Для фиксированого формата нужно писать
PkgReserved: Array[0..128] of Char;


 
SkyRanger ©   (2004-06-07 13:28) [10]

Спасибо, попробую...


 
SkyRanger ©   (2004-06-08 05:32) [11]

>А почему бы несделать формат с фиксированой длиной блока? Тогда и >указатель непонадовится на следующий блок.
Указатели нужны, чтобы без проблем можно было добавить любое количество файлов в любое место списка, это сделать несколько проще чем в массив, пусть и динамический.
>FillChar(var X; Count: Integer; Value: Byte)
Спасибо, никак не мог вспомнить как ее зовут %)
>Еще стоит использовать packed record тогда небудет выравнивания. >Для фиксированого формата нужно писать
>PkgReserved: Array[0..128] of Char;
Сделал и толку ноль. Как мусор был, так он и остается :(


 
SkyRanger ©   (2004-06-08 08:23) [12]

Наконец разобрался с этой проблемой.
Оказывается BlockWrite записывает в файл данные из буфера и если не указано сколько то записываются блоки по 128 байт. Т.е. по-моему получилось что он пытался записать в файл данные не только которые я ему указывал, но следующий участок памяти до 128 байт.
Я использовал FileOpen и FileWrite и вроде все заработало нормально, не считая некоторых мелочей...


 
ЮЮ ©   (2004-06-08 08:27) [13]

>Сделал и толку ноль. Как мусор был, так он и остается :(
Не нравится мусор, заполняй строку справа пробелами до объявленной длины


 
SkyRanger ©   (2004-06-08 11:22) [14]

Нее мусор был не поэтому, а потому что программа брала вместе с нужными данными участок памяти до заполнения буфера. Т.е. записывала вместо строки file1.txt все что находилось в памяти следом за выделенной под переменную памяти, отсюда и мусор...


 
wicked ©   (2004-06-08 11:38) [15]

прогресс...
Reset/BlockWrite -> FileOpen/FileWrite ->???... :)

советую изучить иерархию классов TStream, TFileStream, TMemoryStream и забыть о FileOpen/FileWrite... намного более гибкий подход...
насчет сборища файлов - почитать о IStorage/IStream... тогда пропадет желание изобретать велосипеды... могу подбросить примерчик обертки сих интерфейсов в delphi"йский TStream, но правда на builder и с минимумом комментариев...
если же нужен портабельный вариант - http://www.wotsit.org и ищем формат zip-файлов...

ой, что это я советов раздавался... ;)


 
SkyRanger ©   (2004-06-09 09:00) [16]

Я просто стараюсь писать таким образом, чтобы поменьше зависить от стандартных классов Delphi так как енто череповато увелиением, существенным, размера экзешника...
Стримы меня не очень привлекают, может потому что они используют родные средства винды активно, что на мой взгляд не есть гуд...

А вообще сапасибо за советы! %) Учту на будущее...
P.S.
За линк пасиба %)



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

Форум: "Основная";
Текущий архив: 2004.06.20;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.037 c
14-1086183707
Alibaba
2004-06-02 17:41
2004.06.20
Video -> CD/DVD


9-1070178138
Cash
2003-11-30 10:42
2004.06.20
Как работать с альфой


1-1086096414
Kiloper
2004-06-01 17:26
2004.06.20
DranDrop для TLabel


14-1085930017
Petr V. Abramov
2004-05-30 19:13
2004.06.20
Всем писателям операционных систем!


3-1085668722
zdn
2004-05-27 18:38
2004.06.20
Как в FireBIrd добавить?





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