Конференция "Игры" » Большой файл для хранения данных [Delphi, DirectX 9]
 
  • ElectriC © (26.05.07 20:29) [0]
    Как создать большой файл для хранения файлов(графических, текстовых, музыкальных и пр.), а потом из загружать в программу из
    этого файла, как это сделано в, например, FlatOut и пр?
    P.S. По возможности сделать файл, чтобы его нельзя было просматривать/редактировать!!!
  • XProger © (26.05.07 21:40) [1]
    Придумать и сделать. Самое простое - zip сжатие под паролем ;)
  • @!!ex © (26.05.07 21:50) [2]
    У меня есть модулек для таких целей.
    Просто создает гигантских архив, умеет читать из него.
    В начале таблица с файлами:
    Имя, смещение, размер, тип сжатия(На данный момент сжатие еще не сделал).
    Ну и соответственно сделано чтение из него по принципу:
    Проис классик в память прочитать конкретный файлих из арзива, потом по этому участку памяти создаем TMemoryStream и работаем с ним как со стримом(правда я не стримы юзаю, но принцип тот же).
  • homm © (26.05.07 22:32) [3]
    > По возможности сделать файл, чтобы его нельзя было просматривать/редактир
    > овать!!!

    Выделить в проводнике, нажать кнопку shift, и не отпуская ее delete.
  • @!!ex © (26.05.07 22:58) [4]
    Если стоят Нортоновские утилиты, то не поможет. :)
    У меня тут было, херакс и начинает винда матерится, что ей места мала... Ладно, думаю, ща. Нахожу "лишние" файлики, убиваю...
    Через пару дней обращаю внимания, что она опять матерится... При чем места стало еще меньше.. Уже буквально несколько десятков метров..
    Нахожу еще "лишних" файликов, скрипя сердцем удаляю или перемещаю на другие диски... Проверяю... Места больше не стало... Чо за на?
    А это Нортон, скотина файлики хапрещает удалять, вернее он их у себя сохраняет.... Сколько ни удаляй, места не прибавится, и всегда их можно восстановить мля... ПРишло его отключить на системном диске....
  • homm © (26.05.07 23:17) [5]
    ПРишло его отключить на системном диске....

    Правый клик на корзине/Очистить корзину Norton.
  • ElectriC © (26.05.07 23:32) [6]

    > У меня есть модулек для таких целей.Просто создает гигантских
    > архив, умеет читать из него.В начале таблица с файлами:Имя,
    >  смещение, размер, тип сжатия(На данный момент сжатие еще
    > не сделал).Ну и соответственно сделано чтение из него по
    > принципу:Проис классик в память прочитать конкретный файлих
    > из арзива, потом по этому участку памяти создаем TMemoryStream
    > и работаем с ним как со стримом(правда я не стримы юзаю,
    >  но принцип тот же).

    Можешь скинуть!;))
    Или хотя бы подскажи, где почитать об этом?
  • ElectriC © (26.05.07 23:33) [7]

    > Выделить в проводнике, нажать кнопку shift, и не отпуская
    > ее delete.

    И при чём тут это???
  • Vovan #2 (26.05.07 23:43) [8]
    Удалено модератором
  • homm © (27.05.07 00:01) [9]
    > И при чём тут это???

    Это то о чем сказано в сабже, делает непросматриваемым и не редактируемым. Кроме физического удаления носителей, это единственный способ.
  • homm © (27.05.07 00:04) [10]
    Удалено модератором
  • Vovan #2 (27.05.07 00:05) [11]
    Удалено модератором
  • ANTPro © (27.05.07 00:06) [12]
    > [7] ElectriC ©   (26.05.07 23:33)

    У Vga спроси у него пакман с LZMA, UCL есть.
    Его SVN: http://vgasoft.googlecode.com/svn/PakManDLL
  • Vga © (27.05.07 00:56) [13]
    Бинарник с бредовым хелпом: http://vgasoft.googlecode.com/svn/Binaries/PakManDLL
  • Yashin © (27.05.07 22:24) [14]
    В GlScene модуль есть GLVfsPak. Я сам тоже писал такой модуль как у @!!ex, но я таблицу файлов делал в конце, так удобнее можно потом добавлять файлы, и у меня было сжатие через zlib. Но жаль после формата редко что выживает. Будет время перепишу заного это не сложно.
    Вот вам модуль с примерчиком, не знаю будет работать. претензии не предъявлять, не нравится качайте GlScene.
    http://ifolder.ru/2152922
  • ElectriC © (28.05.07 15:18) [15]

    > Yashin ©

    Спасибо!
  • @!!ex © (28.05.07 19:39) [16]
    > Правый клик на корзине/Очистить корзину Norton.

    Знаим, знаим. Но винда постоянно темповскими файлами ворочает. Поэтому место забивалось за один-два дня. Вот и отключил. Тем более что нафиг не надо.


    > [14] Yashin ©   (27.05.07 22:24)

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

    Вот код модуля:
    unit Extractor;

    interface
    uses Windows, SysUtils;

    var
     VERSION:byte = 1;
     BufferSize:DWORD = 1048576;
     ArchiveIsPriority:boolean = false;

     //  Файл_есть_в_архиве & (Архив_приоеритетен | !Файл_есть_на_диске)

    type
     PTextFile = ^TTextFile;

     TArchiveItem = record
       Name:array[0..255] of char;
       State:DWORD;                 //2 - Normal, 3 - LZW
       Offset:DWORD;
       Size:DWORD;
     end;

     TExtractor = class
     public
       Constructor Create;                                     //Создаем экземпляр объекта
       Destructor  Destroy; override;                          //Освобождением данных
       Procedure   LoadFromFile(const FileName:string);        //Загружаем архив
       Procedure   SetPath(const Path:string);                 //Устанавливаем абсолютный путь нахождения архива
       Function    GetCount:integer;                           //Получаем количество файлов в архиве
       Function    GetFileIndex(const FileName:string):integer;//Получаем индекс файла. Если файла в архиве нет, то -1
       Function    GetData(FileIndex:integer):Pointer;         //Получаем указатель на данные файла. Потом их надо освободить!
       Function    GetSize(FileIndex:integer):DWORD;           //Получаем размер файла
       Function    GetName(FileIndex:integer):string;          //получаем имя файла
     protected
       AbsolutePath:string;
       Count:integer;
       Items:array of TArchiveItem;
       FileHandle:integer;
     end;

     TSimpleFile = class
     public
       Constructor Create(const FileName:string);
       Destructor  Destroy();override;
       Function    EoF:boolean;
     protected
       Data:Pointer;
       Position:PByte;
       Size:DWORD;
     end;

     TTextFile = class(TSimpleFile)
     public
       Function    ReadString:string;
       Function    ReadTrimString:string;
     end;

     TIntegerFile = class(TSimpleFile)
     public
       Function    ReadInteger:integer;
     end;

    implementation
    uses Data;

    { TExtractor }

    const
     ERR_OUTOFRANGE = 'File Index in DPG archive out of range';
     ERR_ENDOFFILE = 'Riched End Of File';

    constructor TExtractor.Create;
    begin
     FileHandle:=0;
     Count:=0;
     SetLength(Items,Count);
    end;

    destructor TExtractor.Destroy;
    begin
     Count:=0;
     SetLength(Items,Count);
     if FileHandle<>0 then CloseHandle(FileHandle);
    end;

    function TExtractor.GetCount: integer;
    begin
     Result:=Count;
    end;

    function TExtractor.GetData(FileIndex: integer): Pointer;
    begin
     if (FileIndex<0) or (FileIndex>Count-1) then
       raise Exception.Create(ERR_OUTOFRANGE);
     Result:=AllocMem(Items[FileIndex].Size);
     FileSeek(FileHandle,Items[FileIndex].Offset,0);
     FileRead(FileHandle,Result^,Items[FileIndex].Size);
    end;

    function TExtractor.GetFileIndex(const FileName: string): integer;
    var
     Index:integer;
     S:string;
    begin
     S:=UpperCase(FileName);
     Result:=-1;
     for Index:=0 to Count-1 do
       if AbsolutePath+Items[Index].Name=S then begin
         Result:=Index;
         exit;
       end;
    end;

    function TExtractor.GetName(FileIndex:integer): string;
    begin
     if (FileIndex<0) or (FileIndex>Count-1) then
       raise Exception.Create(ERR_OUTOFRANGE);
     Result:=Items[FileIndex].Name;
    end;

    function TExtractor.GetSize(FileIndex: integer): DWORD;
    begin
     if (FileIndex<0) or (FileIndex>Count-1) then
       raise Exception.Create(ERR_OUTOFRANGE);
     Result:=Items[FileIndex].Size;
    end;

    procedure TExtractor.SetPath(const Path: string);
    begin
     AbsolutePath:=UpperCase(Path);
    end;

    procedure TExtractor.LoadFromFile(const FileName: string);
    var
     Vers:byte;
     Index:DWORD;
     S:string;
    begin
     if FileHandle<>0 then begin
       FileClose(FileHandle);
       Count:=0;
       SetLength(Items,Count);
       AbsolutePath:='';
     end;

     FileHandle:=FileOpen(FileName,fmOpenRead);
     FileRead(FileHandle,Vers,sizeof(Vers));
     FileRead(FileHandle,Count,sizeof(Count));
     SetLength(Items,Count);

     for Index:=0 to Count-1 do begin
       FileRead(FileHandle,Items[Index],sizeof(TArchiveItem));
       S:=UpperCase(Items[Index].Name);
       CopyMemory(@Items[Index].Name[0],@S[1],Length(S));
     end;
    end;

    { TTextFile }

    constructor TSimpleFile.Create(const FileName: string);
    var
     Index:integer;
     Handle:integer;
    begin
     Index:=Archive.GetFileIndex(FileName);
     if (Index>-1) and (ArchiveIsPriority or not FileExists(FileName)) then begin
       Data:=Archive.GetData(Index);
       Size:=Archive.GetSize(Index);
     end
     else
     if FileExists(FileName) then
     begin
       Handle:=FileOpen(FileName,fmOpenRead);
       Size:=FileSeek(Handle,0,2);
       FileSeek(Handle,0,0);

       Data:=AllocMem(Size);
       FileRead(Handle,Data^,Size);
       FileClose(Handle);
     end
     else
       raise Exception.Create('File not found: \"'+FileName+'\"');
     Position:=Data;
    end;

    destructor TSimpleFile.Destroy;
    begin
     FreeMem(Data,Size);
     inherited;
    end;

    function TSimpleFile.EoF: boolean;
    begin
     Result:=Integer(Position)-Integer(Data)>=Size;
    end;

    function TTextFile.ReadString: string;
    begin
     Result:='';
     if not EoF then begin
       while (not EoF) and (Position^<>13) do begin
         Result:=Result+chr(Position^);
         inc(Position);
       end;
       if not EoF then
         inc(Position,2);
     end
     else
       raise Exception.Create(ERR_ENDOFFILE);
    end;

    function TTextFile.ReadTrimString: string;
    begin
     Result:=Trim(ReadString);
    end;

    { TIntegerFile }

    function TIntegerFile.ReadInteger: integer;
    begin
     Result:=0;
     if not EoF then begin
       Result:=PInteger(Position)^;
       inc(Position,sizeof(Integer));
     end
     else
       raise Exception.Create(ERR_ENDOFFILE);
    end;

    end.



    Если надо, есть софт для запаковки/распаковки, запаковка - с поддержкой плагинов.
  • @!!ex © (28.05.07 19:43) [17]
    P.S>
    Строчки
    VERSION:byte = 1;
    BufferSize:DWORD = 1048576;


    можно убить, они не юзаются.
  • ElectriC © (29.05.07 00:05) [18]

    > @!!ex

    Спасибо за исходник ;)))
  • Vga © (02.06.07 08:20) [19]
    Кстати, о редактировании. При минимальном навыке файлы типа @llex'овского вскрываются за 5 минут. Плюс некоторое время на нахождение и извлечение декодеров, если такие есть (сжатие, шифрование). VSPak (выше посты про PakMan) чуть сложнее, но в принципе тоже достаточно просто вскрывается.
 
Конференция "Игры" » Большой файл для хранения данных [Delphi, DirectX 9]
Есть новые Нет новых   [134431   +5][b:0][p:0.005]