Forum in READ ONLY mode! All questions and discussions on Discord official server, invite link: https://discord.gg/VxsGzJ7

Запись структуры в файл

тут можно задать вопрос по скриптингу
Post Reply
yuras
Novice
Novice
Posts: 142
Joined: 11.01.2011 10:34

Запись структуры в файл

Post by yuras »

Code: Select all

Program tst;
type  bmFileHeader = record	
    Typf : word;        
    Size : longint;     
    Res1 : word;       
    Res2 : word;       
    OfBm : longint;  
  end;
var
data:bmFileHeader ;
File:TFileStream;
begin
data.Typf:=16973;
data.size:=1024;
data.Res1:=0;
data.Res2:=0;
data.OfBm:=62;
file := TFileStream.Create('D:\test',fmcreate);
file.seek(0,soFromEnd);
file.writebuffer(data,Length(data)); 
file.Free;
end;
вот пример, при компиляции выдает ошибку, 'type mismatch' на writebuffer. как правильно записать record в файл? Ну и прочитать оттуда тоже)
User avatar
Vizit0r
Developer
Developer
Posts: 3958
Joined: 24.03.2005 17:05
Contact:

Re: Запись структуры в файл

Post by Vizit0r »

sizeof всю жизнь было, а не Length
хотя, честно говоря, не проверял в ПС ни разу.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
yuras
Novice
Novice
Posts: 142
Joined: 11.01.2011 10:34

Re: Запись структуры в файл

Post by yuras »

Vizit0r wrote:sizeof всю жизнь было, а не Length
хотя, честно говоря, не проверял в ПС ни разу.
с sizeof тоже самое. если стринговую переменную ставить, компиляция проходит.
User avatar
Vizit0r
Developer
Developer
Posts: 3958
Joined: 24.03.2005 17:05
Contact:

Re: Запись структуры в файл

Post by Vizit0r »

потому что правильно

Code: Select all

file.writebuffer(data,sizeof(bmFileHeader));
Потому что тебе надо записать размер записи, а не переменной.
размер переменной в данном случае равен 4, ибо указатель на запись. но ПС в такие тонкости не вникает, и дает ошибку. оно и к лучшему.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
yuras
Novice
Novice
Posts: 142
Joined: 11.01.2011 10:34

Re: Запись структуры в файл

Post by yuras »

Vizit0r wrote:потому что правильно

Code: Select all

file.writebuffer(data,sizeof(bmFileHeader));
Потому что тебе надо записать размер записи, а не переменной.
размер переменной в данном случае равен 4, ибо указатель на запись. но ПС в такие тонкости не вникает, и дает ошибку. оно и к лучшему.
Да, логично, но все равно та-же ошибка.
(tst.sc at 1214:44): Type mismatch
User avatar
Vizit0r
Developer
Developer
Posts: 3958
Joined: 24.03.2005 17:05
Contact:

Re: Запись структуры в файл

Post by Vizit0r »

а, пардон. я вчера проверил, вроде откомпилировалось нормально.
сутра проверил - глюк :)
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
User avatar
Vizit0r
Developer
Developer
Posts: 3958
Joined: 24.03.2005 17:05
Contact:

Re: Запись структуры в файл

Post by Vizit0r »

изменено, причина: проблема в том, что первым параметром должен быть String, а не в sizeof.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
VeL
Novice
Novice
Posts: 54
Joined: 03.12.2010 18:15

Re: Запись структуры в файл

Post by VeL »

Структуру нельзя никак записать в файл?
User avatar
Vizit0r
Developer
Developer
Posts: 3958
Joined: 24.03.2005 17:05
Contact:

Re: Запись структуры в файл

Post by Vizit0r »

вот пример с сохранением структур из дельфийского исходника стелса.

Code: Select all

type TShard_v_5 = record     
    ShardName : String[50];
    IP : String[49];
    Port : Cardinal;
    UseProxy : Boolean;
    ProxyIP : String[15];
    ProxyPort : Word;
    ProxyAuthMethod : Byte;
    ProxyAuthLogin : String[48];
    TooltipDelay : Word;
    ProxyAuthPass : String[48];
    EnableRazorSupport : Boolean;
    ProxyType : Byte;
    EncryptionEnabled : Boolean;
    Ver : TClientVer;
    UOMULPath : String[255];
    SelClient : Byte;
    NulTargets : boolean;
  end; 

PShard_v_5 = ^TShard_v_5;

var   filehwnd : HWND;
ShardData : TShard_v_5;
WriteBytes, wb : Cardinal;
  WriteResult : Boolean;


  filehwnd  := CreateFile(pChar(ShardsPath), GENERIC_WRITE, 0, Nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  if (filehwnd = INVALID_HANDLE_VALUE) then
  begin
    AddToLog("System", MSG_GLOBALSETUP_ERROR, "Error with opening: INVALID HANDLE VALUE");
    Exit;
  end;
  //Если файл открыли нормально, то начинаем записывать
      ShardData := PShard_v_5 (ShardsList.Items[i])^;
      //Далее сама запись
      while (WriteBytes < BlockSize) do
      begin
        WriteResult := WriteFile(filehwnd, ShardData^, BlockSize, wb, Nil);
        if not WriteResult then
        begin
          MessageBox(Application.Handle, 'Error with saving shards. WriteResult = False.', 'Save shards error', MB_OK);
          CloseHandle(filehwnd);
          Exit;
        end;
        if (wb = 0) then
        begin
          MessageBox(Application.Handle, 'Error with saving shards. WB = 0.', 'Save shards error', MB_OK);
          CloseHandle(filehwnd);
          Exit;
        end;
        WriteBytes := WriteBytes + wb;
      end;

  CloseHandle(filehwnd);
и это отличный пример того, как делать не надо.


Надо как-то так (переписал 10 минут назад код):

Code: Select all

  procedure SaveShardsList(savefilename : string = 'shards.dat');
var i : Integer;
  ShardData : TShard_v_5;
  ShardsPath : String;
  filestr : TFileStream;
  WriteResult : Boolean;
  ShardsVersion : Cardinal;
  mode : Word;
begin
  if ShardsList.Count = 0 then Exit;
  ShardsPath := StealthPath + savefilename;
  if FileExists( savefilename) then
    mode := fmOpenReadWrite or fmShareDenyWrite
  else
    mode := fmCreate;
  try
    filestr := TFileStream.Create(savefilename,mode);
  except
    Exit;
  end;
  //Если файл открыли нормально, то начинаем записывать
  //Сначала запишем версию сохраняемых данных
  ShardsVersion := 5;
  if filestr.Write(ShardsVersion,4) <> 4 then
  begin
    MessageBox(Application.Handle, 'Error with saving shards. ShardsVersion not written', 'Save shards error', MB_OK);
    filestr.Free;
    Exit;
  end;


  if (ShardsList.Count > 0) then
  for i := 0 to ShardsList.Count - 1 do
  begin
    ShardData := PShard_v_5 (ShardsList.Items[i])^;
    //Далее сама запись
    WriteResult := filestr.Write(ShardData,SizeOf(TShard_v_5)) = SizeOf(TShard_v_5);
    if not WriteResult then
    begin
      MessageBox(Application.Handle, 'Error with saving shards. WriteResult = False.', 'Save shards error', MB_OK);
      filestr.Free;
      Exit;
    end;
  end;
  filestr.Free;
end;
понятия не имею, как оно будет вести себя на ПС, но на 6м стелсе, где вместо ПС встроен PAX - точно будет работать.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
Post Reply