Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Как сохранить в файл запись (record) с динамическими массивами?  [new]
registered
Member

Откуда:
Сообщений: 30
Как сохранить в файл запись (record) с динамическими массивами?
file of, естественно, не работает.
Вручную сохранять по одной переменной - не хочется.
5 дек 18, 06:51    [21753888]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
Vlad F
Member

Откуда:
Сообщений: 309
registered,

Покажи, что именно ты имеешь ввиду под "запись (record) с динамическими".
5 дек 18, 08:23    [21753908]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
zinpub
Member

Откуда:
Сообщений: 294
procedure SaveArray(Stream: TStream; const iArr: TDynArray);
var
  aLen: Integer;
begin
  aLen := Length(iArr);
  Stream.WriteBuffer(Pointer(iArr)^, aLen * SizeOf(Integer));
5 дек 18, 08:46    [21753922]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3590
registered,

в общем виде только серелиализацию писать, например с помощью TypInfo
5 дек 18, 08:52    [21753926]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 59449
registered> file of, естественно, не работает.

Покажи код.

Posted via ActualForum NNTP Server 1.5

5 дек 18, 09:21    [21753944]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
registered
Member

Откуда:
Сообщений: 30
Да любую, хотя бы, такую.

type trec=record
  a:integer;
  c:array of integer;
  b:double;
  end;

var rec:array of trec;
5 дек 18, 10:48    [21754020]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 12558
Может, JSON?
5 дек 18, 11:13    [21754041]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
Vlad F
Member

Откуда:
Сообщений: 309
registered,

Так тебе запись с динамическими массивами или массив записей с массивами?
В первом случае можно в бинарном виде без цикла за три последовательных акта записи,
во втором в общем случае без цикла, имхо, не обойтись.
5 дек 18, 13:10    [21754275]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
registered
Member

Откуда:
Сообщений: 30
Массив записей с массивами.
Тут ещё придумал, что можно с помощью Move скопировать всё содержимое записи, за исключением указателей. А вот как бы ещё динамический массив скопировать, тоже напрямую из памяти, вместе с длиной? И потом загрузить из файла таким же образом.
5 дек 18, 13:20    [21754286]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
Vlad F
Member

Откуда:
Сообщений: 309
registered,

См. выше про три порции. Первый move() это собственно сам record. Потом пишешь длину массива и затем опять через move() содержимое динмассива. Читаешь в том же порядке, только перед третьим чтением делаешь массиву нужный (прочитанный вторым чтением) SetLenth().
5 дек 18, 14:47    [21754440]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
registered
Member

Откуда:
Сообщений: 30
Динамический массив же не копируется через Move, копируется только указатель.
5 дек 18, 14:59    [21754464]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
Vlad F
Member

Откуда:
Сообщений: 309
registered,

А мужики-то и не знают.)))
5 дек 18, 15:02    [21754471]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
registered
Member

Откуда:
Сообщений: 30
Ну так пусть мужики пример приведут, что-ли, однако.
5 дек 18, 19:39    [21754876]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
MBo
Member

Откуда:
Сообщений: 64
registered, для динамических массивов, элементы которых не содержат, в свою очередь, динамических элементов (в т.ч. строк), можно копировать тело массива так:

    Move(SrcArr[0], DstArr[0], SizeOf(SrcArr[0])*Length(SrcArr));


Общее правило для использования строк, дин. массивов в качестве нетипизированного var/const параметра - разыменовать указатель (т.к. компилятор сам возьмёт адрес переменной)

Вариант:
    MemoryStream.ReadBuffer(PChar(AString)^ ...
5 дек 18, 19:48    [21754889]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
Vlad F
Member

Откуда:
Сообщений: 309
registered,

Начинаю догадываться, - студент? курсовая? А поиск в сети по ключевым словам еще не проходили?
К тебе же третий от начала пост был на эту тему, - спроецируй его самостоятельно на Move().
5 дек 18, 19:51    [21754896]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
asutp2
Member

Откуда: Тюмень
Сообщений: 361
в любом случае нужно еще длину поля динамического массива в record тоже записывать)))
5 дек 18, 20:10    [21754918]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
asutp2
Member

Откуда: Тюмень
Сообщений: 361
registered
Ну так пусть мужики пример приведут, что-ли, однако.
сначала студент напишет свой вариант кода, вот тогда и будем смотреть, что ты написал и что нужно исправить.

А если студент этого не хочет делать (выкладывать свой вариант), то тогда бегом в режим заказа платной разработки, коль сам не можешь/не хочешь
5 дек 18, 20:12    [21754921]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
Vlad F
Member

Откуда:
Сообщений: 309
asutp2,

Это только если делать транспортабельный (считываемый другими приложениями) формат.
А в своем собственном длину отдельного элемента и так знает. Другое дело что в рекорд
можно было ввести длину самого динамического массива, тогда писать/читать можно
было бы не за три итерации, а за две.
5 дек 18, 20:20    [21754935]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
gssbox
Member

Откуда:
Сообщений: 65
Делал такое использовал RTTI и дженерики, но в конечном счете пришлось отказаться от этой идеи так как тормозило при интенсивных нагрузках.

Вот пример кода:
+
type
  TPrmName = array[0..127] of AnsiChar;

type
 TPrmBlock = packed record
   PrmName    : TPrmName;  //Имя параметра
   PrmType    : TTypeKind; //Тип параметра
   TypeSize   : Integer;   //Размер параметра
 end;

procedure TUFF<T1, T2, T3, T4>.ReadOrWriteDataToRecordPrm<T>(Param: Pointer; PrmBlock: TPrmBlock; FS: TFileStream; Mode: Byte);
var
  RType     : TRTTIType;
  Fields    : TArray<TRttiField>;
  I         : Integer;
  P         : Pointer;
  RecValue  : TValue;
  ArrLength : NativeInt;
  TypeSize  : NativeInt;
  B         : TArray<Byte>;
  PrmSize   : Integer;
  S         : String;
  pS        : PString;
  NotFound  : Boolean;
begin

  NotFound := true;
  RType := TRTTIContext.Create.GetType(TypeInfo(T));

  Fields := RType.GetFields;
  for I := 0 to High(Fields) do
   begin
       if Assigned(Fields[I].FieldType) then
        begin
                  if UpperCase(Fields[I].Name) = UpperCase(String(PrmBlock.PrmName)) then {Совпали имена параметров}
                    begin

                     if (Fields[I].FieldType.TypeKind = PrmBlock.PrmType){ and
                        (Fields[I].FieldType.TypeSize = PrmBlock.TypeSize)} then {Совпал тип параметра}
                      begin
                       {Получаем указатель на конкретный параметр из record-a}
                       P := Pointer(Integer(Param) + Fields[I].Offset);

                                       case Mode of
                                            ReadMode  : begin
                                                               case Fields[I].FieldType.TypeKind of
                                                                tkUString : begin {String}
                                                                              {Читаем длину строки}
                                                                              FS.Read(PrmSize, SizeOf(PrmSize));
                                                                              {Загружаем строку во временный массив B, и перекодируем в String}
                                                                              SetLength(B, PrmSize);
                                                                              FS.Read(B[Low(B)], PrmSize);
                                                                              S  := TEncoding.UTF8.GetString(B);
                                                                              pS := P;
                                                                              SetLength(pS^, Length(S));
                                                                              move(Pointer(S)^, PPointer(P)^^, Length(S) * StringElementSize(S));
                                                                            end;

                                                                tkDynArray: begin {Динамические массивы}
                                                                             FS.Read(PrmSize, SizeOf(PrmSize));
                                                                             RecValue  := Fields[I].GetValue(Param);
                                                                             TypeSize  := RecValue.TypeInfo.TypeData^.elSize;
                                                                             ArrLength := PrmSize div TypeSize;
                                                                             {Dimension - размерность массива 1- 1D, 2 - 2D и т.д.}
                                                                             if ArrLength > 1024 * 1024 * 10 then
                                                                              begin
                                                                                UpdateMessage('BigSize: ' + IntToStr(PrmSize) + ' - ' + IntToStr(FS.Position));
                                                                                ArrLength := 0;
                                                                              end;
                                                                             DynArraySetLength(PPointer(P)^, RecValue.TypeInfo, 1{Dimension}, @ArrLength);
                                                                             FS.Read(PPointer(P)^^, ArrLength * TypeSize);
                                                                            end;

                                                                            else
                                                                             FS.Read(P^, Fields[I].FieldType.TypeSize);
                                                                end;
                                                        end;

                                            WriteMode : begin
                                                               case Fields[I].FieldType.TypeKind of

                                                                tkUString : begin {String}
                                                                              {Преобразуем строку в UTF8 и помещаем ее в массив}
                                                                              B := TEncoding.UTF8.GetBytes(PPointer(P)^);
                                                                              {Пишем длину строки}
                                                                              PrmSize := Length(B);
                                                                              FS.Write(PrmSize, SizeOf(PrmSize));
                                                                              {Пишем строку в поток в кодировке UTF8}
                                                                              FS.Write(B[Low(B)], Length(B));
                                                                            end;

                                                                tkDynArray: begin {Динамические массивы}
                                                                             RecValue  := Fields[I].GetValue(Param);
                                                                             ArrLength := RecValue.GetArrayLength;
                                                                             TypeSize  := RecValue.TypeInfo.TypeData^.elSize;
                                                                             PrmSize   := ArrLength * TypeSize;
                                                                             {Пишем размер массива байтах}
                                                                             FS.Write(PrmSize, SizeOf(PrmSize));
                                                                             //PPointer(P)^ - указатель на первый(нулевой) элемент массива
                                                                             {Пишем сам массив}
                                                                             FS.Write(PPointer(P)^^, PrmSize);
                                                                            end;

                                                                            else
                                                                             FS.Write(P^, Fields[I].FieldType.TypeSize);
                                                               end;
                                                        end;
                                       end; {end case ...}

                       NotFound := false;
                       break;
                      end else
                      begin
                        if Mode = ReadMode then
                         begin
                               UpdateMessage(rsTUFFReadOrWriteDataToRecordPrm_Msg1 + String(PrmBlock.PrmName));
                               {Если переменная имеет другой тип данных то просто перемещаем позицию в файле на следующий параметр}
                                if (PrmBlock.PrmType = tkUString) or (PrmBlock.PrmType = tkDynArray) then
                                 begin
                                   FS.Read(PrmSize, SizeOf(PrmSize));
                                   {Параметр отсутствует}
                                   FS.Position := FS.Position + PrmSize;
                                 end else
                                 begin
                                     FS.Position := FS.Position + PrmBlock.TypeSize;
                                 end;
                         end;
                      end; {end if (Fields[I].FieldType.TypeKind = PrmBlock.PrmType) then ...}
                    end; {end if UpperCase(Fields[I].Name) = UpperCase(String(PrmBlock.PrmName)) then ...}
        end else
        begin
          UpdateMessage(rsTUFFReadOrWriteDataToRecordPrm_Msg2 + Fields[I].Name + rsTUFFReadOrWriteDataToRecordPrm_Msg3);
         // exit;
        end; {end if Assigned(Fields[I].FieldType) then}
   end; {end for I := 0 to High(Fields) do}

   if NotFound and (Mode = ReadMode) then
     begin
     UpdateMessage(rsTUFFReadOrWriteDataToRecordPrm_Msg4 + String(PrmBlock.PrmName) + rsTUFFReadOrWriteDataToRecordPrm_Msg5);
     {Если параметр несуществует то перемещаем позицию в файле}
      if (PrmBlock.PrmType = tkUString) or (PrmBlock.PrmType = tkDynArray) then
       begin
         FS.Read(PrmSize, SizeOf(PrmSize));
         FS.Position := FS.Position + PrmSize;
       end else
       begin
         FS.Position := FS.Position + PrmBlock.TypeSize;
       end;
    end;
end;
5 дек 18, 20:22    [21754940]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
registered
Member

Откуда:
Сообщений: 30
Vlad F
Начинаю догадываться, - студент? курсовая?
Совершенно неверно!
В общем, тем, кто начал писать про мужиков, студентов, - отвечать нет желания.
Остальным - спасибо (получилось, код приводить не буду).
Относительно "Динамический массив же не копируется через Move" - было
Move(SrcArr, DstArr[0], ...);
а нужно было
Move(SrcArr[0], DstArr[0],, ...);
5 дек 18, 20:29    [21754946]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
Vlad F
Member

Откуда:
Сообщений: 309
registered,

Ну и слава богу.
5 дек 18, 20:37    [21754954]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
asutp2
Member

Откуда: Тюмень
Сообщений: 361
registered
Vlad F
Начинаю догадываться, - студент? курсовая?
Совершенно неверно!
В общем, тем, кто начал писать про мужиков, студентов, - отвечать нет желания.
Остальным - спасибо (получилось, код приводить не буду).
Относительно "Динамический массив же не копируется через Move" - было
Move(SrcArr, DstArr[0], ...);
а нужно было
Move(SrcArr[0], DstArr[0],, ...);
хотелось бы увидеть этот код, если он вообще есть))))
5 дек 18, 22:38    [21755094]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
white_nigger
Member

Откуда: Тула
Сообщений: 1944
registered
Остальным - спасибо (получилось, код приводить не буду).
Относительно "Динамический массив же не копируется через Move" - было
Move(SrcArr, DstArr[0], ...);
а нужно было
Move(SrcArr[0], DstArr[0],, ...);
...и будет это работать только до тех пор пока элементы массива сами не станут управляемым типом или его содержащим контейнером...
5 дек 18, 22:40    [21755095]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3590
gssbox
Делал такое использовал RTTI и дженерики, но в конечном счете пришлось отказаться от этой идеи так как тормозило при интенсивных нагрузках.
довольно много выделений памяти и цикл с поиском параметров + то что white_nigger написал

можно ещё допиливать и допиливать
5 дек 18, 23:23    [21755121]     Ответить | Цитировать Сообщить модератору
 Re: Как сохранить в файл запись (record) с динамическими массивами?  [new]
registered
Member

Откуда:
Сообщений: 30
А если есть вложенная запись

type ta=record
s:string;
i:integer;
end;

type trec=record;
a:ta;
i:integer;
end;

var rec:trec;


То, если скопировать память переменной rec, то, вместо указателя на структуру a, может оказаться левый адрес. Вероятно, то же и с s:string;. И даже отдельное копирование переменной a не спасёт, потому что адрес затёрт. Что делать, однако?
Код привести не могу, потому что "в продакшене"... э-э, в общем, тестовый проект с просто записью и чтением из файла - работает, а реальный - нет.

Где-то так:
move(str1[1],rec,length(str1));
move(str2[1],rec.a,length(str2));
setlength(rec.a.s,length(str3));
move(str3[1],rec.a.s[1],length(str3));

Крэшится на втором "move".
str1, str2, str3 - это ansistring, с данными, соответственно, rec, rec.a, rec.a.s.
9 дек 18, 19:37    [21758553]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Delphi Ответить