powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как сохранить в файл запись (record) с динамическими массивами?
45 сообщений из 45, показаны все 2 страниц
Как сохранить в файл запись (record) с динамическими массивами?
    #39742643
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как сохранить в файл запись (record) с динамическими массивами?
file of, естественно, не работает.
Вручную сохранять по одной переменной - не хочется.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742654
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

Покажи, что именно ты имеешь ввиду под "запись (record) с динамическими".
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742661
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: pascal
1.
2.
3.
4.
5.
6.
procedure SaveArray(Stream: TStream; const iArr: TDynArray);
var
  aLen: Integer;
begin
  aLen := Length(iArr);
  Stream.WriteBuffer(Pointer(iArr)^, aLen * SizeOf(Integer));
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742662
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

в общем виде только серелиализацию писать, например с помощью TypInfo
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742674
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered> file of, естественно, не работает.

Покажи код.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742716
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да любую, хотя бы, такую.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
type trec=record
  a:integer;
  c:array of integer;
  b:double;
  end;

var rec:array of trec;
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742730
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может, JSON?
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742797
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

Так тебе запись с динамическими массивами или массив записей с массивами?
В первом случае можно в бинарном виде без цикла за три последовательных акта записи,
во втором в общем случае без цикла, имхо, не обойтись.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742803
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Массив записей с массивами.
Тут ещё придумал, что можно с помощью Move скопировать всё содержимое записи, за исключением указателей. А вот как бы ещё динамический массив скопировать, тоже напрямую из памяти, вместе с длиной? И потом загрузить из файла таким же образом.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742868
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

См. выше про три порции. Первый move() это собственно сам record. Потом пишешь длину массива и затем опять через move() содержимое динмассива. Читаешь в том же порядке, только перед третьим чтением делаешь массиву нужный (прочитанный вторым чтением) SetLenth().
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742878
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Динамический массив же не копируется через Move, копируется только указатель.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39742880
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

А мужики-то и не знают.)))
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743081
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну так пусть мужики пример приведут, что-ли, однако.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743089
MBo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
MBo
Гость
registered, для динамических массивов, элементы которых не содержат, в свою очередь, динамических элементов (в т.ч. строк), можно копировать тело массива так:

Код: pascal
1.
    Move(SrcArr[0], DstArr[0], SizeOf(SrcArr[0])*Length(SrcArr));



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

Вариант:
Код: pascal
1.
    MemoryStream.ReadBuffer(PChar(AString)^ ...
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743095
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

Начинаю догадываться, - студент? курсовая? А поиск в сети по ключевым словам еще не проходили?
К тебе же третий от начала пост был на эту тему, - спроецируй его самостоятельно на Move().
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743106
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в любом случае нужно еще длину поля динамического массива в record тоже записывать)))
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743108
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registeredНу так пусть мужики пример приведут, что-ли, однако.сначала студент напишет свой вариант кода, вот тогда и будем смотреть, что ты написал и что нужно исправить.

А если студент этого не хочет делать (выкладывать свой вариант), то тогда бегом в режим заказа платной разработки, коль сам не можешь/не хочешь
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743116
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asutp2,

Это только если делать транспортабельный (считываемый другими приложениями) формат.
А в своем собственном длину отдельного элемента и так знает. Другое дело что в рекорд
можно было ввести длину самого динамического массива, тогда писать/читать можно
было бы не за три итерации, а за две.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743118
gssbox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Делал такое использовал RTTI и дженерики, но в конечном счете пришлось отказаться от этой идеи так как тормозило при интенсивных нагрузках.

Вот пример кода:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
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;

...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743124
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Vlad FНачинаю догадываться, - студент? курсовая?Совершенно неверно!
В общем, тем, кто начал писать про мужиков, студентов, - отвечать нет желания.
Остальным - спасибо (получилось, код приводить не буду).
Относительно "Динамический массив же не копируется через Move" - было
Move(SrcArr, DstArr[0], ...);
а нужно было
Move(SrcArr[0], DstArr[0],, ...);
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743125
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

Ну и слава богу.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743174
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registeredVlad FНачинаю догадываться, - студент? курсовая?Совершенно неверно!
В общем, тем, кто начал писать про мужиков, студентов, - отвечать нет желания.
Остальным - спасибо (получилось, код приводить не буду).
Относительно "Динамический массив же не копируется через Move" - было
Move(SrcArr, DstArr[0], ...);
а нужно было
Move(SrcArr[0], DstArr[0],, ...);хотелось бы увидеть этот код, если он вообще есть))))
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743175
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registeredОстальным - спасибо (получилось, код приводить не буду).
Относительно "Динамический массив же не копируется через Move" - было
Move(SrcArr, DstArr[0], ...);
а нужно было
Move(SrcArr[0], DstArr[0],, ...);...и будет это работать только до тех пор пока элементы массива сами не станут управляемым типом или его содержащим контейнером...
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39743183
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gssboxДелал такое использовал RTTI и дженерики, но в конечном счете пришлось отказаться от этой идеи так как тормозило при интенсивных нагрузках.
довольно много выделений памяти и цикл с поиском параметров + то что white_nigger написал

можно ещё допиливать и допиливать
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39744995
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А если есть вложенная запись

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
type ta=record
s:string;
i:integer;
end;

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

var rec:trec;



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

Где-то так:
Код: pascal
1.
2.
3.
4.
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.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39744999
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

проца move работает с байтами, length(s) возвращает не количество байтов
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745003
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kealon(Ruslan),

у ansistring же длина равна кол-ву байт.

Если перед копированием запомнить указатели на rec.a и rec.a.s, то как их потом вернуть? Т.е., можно присвоить pointer'у адрес rec.a, а обратно - нет.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745004
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registeredу ansistring же длина равна кол-ву байт.У UTF8String кстати тоже.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745007
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

не забывай, что record выравнивается, соответственно между полями записи в памяти может быть разрыв.
у packet record все поля идут строго друг за другом
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745009
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вообще сама задача изначально странная. Я понимаю, что в качестве студенческой задачи пойдет. Но в реальном проекте использовать file of ?
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745016
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хотя, вложенная структура, вроде, хранится не по указателю, а целиком в теле первой. Значит, второе "move" лишнее, и нужно разобраться только со строкой.
Оказалось, там строка string, а в неё копирую ansistring - не работает (это потому что уже кучу раз исправлял, и испортилось, а так там тоже копировалось по байтам).
В общем, перед "move" присвоить
Код: pascal
1.
p:=@rec.a.s;


потом
Код: pascal
1.
move(str1[1],rec,length(str1));


а потом
Код: pascal
1.
pointer(rec.a.s):=p;


и только потом -
Код: pascal
1.
rec.a.s:=str3;



А если "pointer(rec.a.s):=p;" убрать, тогда - error!
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745019
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

мой тебе совет - не делай так .
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745020
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну а как? Передать структуру, а потом её восстановить? Не по одному полю же?
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745026
Фэйтл Эра
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered,

автор
Код: pascal
1.
move(str1[1],rec,length(str1));


А если строка будет пустая - мув не сглючит?
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745035
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registered
Код: pascal
1.
move(str1[1],rec,length(str1));



Ну вот что это за адский пц?..
1) где выделение памяти под копию строки?
2) вы же в курсе, что строка - это указатель?.. т.е. вы копируете данные строки str1 в запись rec, которая у вас имеет размер 12 байт + выравнивание и этим самым портите значения других полей и память за этой записью;
3) копировать строки через move() - это такое себе. Если вам обязательно нужно получить отдельную копию строки в памяти, то делайте так:
Код: pascal
1.
2.
rec.a.s := str1;
UniqueString(rec.a.s); // тут, при необходимости, delphi сама создаст копию строки
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745036
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registeredА если "pointer(rec.a.s):=p;" убрать, тогда - error!

1. p:=@rec.a.s; - сохранили адрес строки s
2. move(str1[1],rec,length(str1)); - затёрли содержимое rec мусором из str1 (в т.ч. и адрес строки s)
3. pointer(rec.a.s):=p; - восстановили адрес строки s (чему равен pointer(rec.a.s) перед этой инструкцией?..)
4. rec.a.s:=str3; - присвоили строке s значение str3, при этом компилятор изменяет значение счётчика ссылок по адресу pointer(s) - 8 (afair).

Теперь догадаетесь почему без 3го шага у вас вылезает ошибка?..
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745175
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alekcvpregistered
Код: pascal
1.
move(str1[1],rec,length(str1));



Ну вот что это за адский пц?..
1) где выделение памяти под копию строки?Так в этой же инструкции строка копируется в запись, для которой не нужно выделять память.
Если выделять память под rec.a.s перед копированием, чтобы получить правильный указатель на строку, то разницы нет (в этом случае).

alekcvp2) вы же в курсе, что строка - это указатель?.. т.е. вы копируете данные строки str1 в запись rec, которая у вас имеет размер 12 байт + выравнивание и этим самым портите значения других полей и память за этой записью;Ну если я сначала сохраняю такую же запись в строку, а потом восстанавливаю, значит такое же кол-во байт должно быть.

alekcvp3) копировать строки через move() - это такое себе. Если вам обязательно нужно получить отдельную копию строки в памяти, то делайте так:
Код: pascal
1.
2.
rec.a.s := str1;
UniqueString(rec.a.s); // тут, при необходимости, delphi сама создаст копию строки

Почему? Если память под 2-ю строку уже выделена нужной длины, то, вроде, как была, так и останется уникальная копия (хоть copy, хоть move), да и обычное присваивание тоже должно сделать уникальную копию.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745294
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registeredalekcvpпропущено...

Ну вот что это за адский пц?..
1) где выделение памяти под копию строки?Так в этой же инструкции строка копируется в запись, для которой не нужно выделять память.
Если выделять память под rec.a.s перед копированием, чтобы получить правильный указатель на строку, то разницы нет (в этом случае).

alekcvp2) вы же в курсе, что строка - это указатель?.. т.е. вы копируете данные строки str1 в запись rec, которая у вас имеет размер 12 байт + выравнивание и этим самым портите значения других полей и память за этой записью;Ну если я сначала сохраняю такую же запись в строку, а потом восстанавливаю, значит такое же кол-во байт должно быть.

Я попытаюсь ещё раз наглядно объяснить. Если всё равно не понимаете, то лучше сначала почитать какие-нибудь книжки по тому как устроена память ПК, что такое строки и указатели и чем они отличаются:
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745349
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpЯ попытаюсь ещё раз наглядно объяснить.
у Саши-GunSmoker'а в блоге весьма наглядная статья-перевод есть
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745375
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В str1 - не мусор, а такое же бинарное представление записи rec, сделанное ранее.
А строка по ссылке запоминается отдельно (в str3), и восстанавливается отдельно, после сохранения адреса rec.a.s, копирования str1 в rec, восстановления адреса, и потом уже присваивание значения строке из str3.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745408
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registeredВ str1 - не мусор, а такое же бинарное представление записи rec, сделанное ранее.
А строка по ссылке запоминается отдельно (в str3), и восстанавливается отдельно, после сохранения адреса rec.a.s, копирования str1 в rec, восстановления адреса, и потом уже присваивание значения строке из str3.
Ты понимаешь, что адрес в rec.a.s действителен только на момент его запоминания? На момент восстановления эта строка может находиться уже в совершенно другом месте и восстановленный адрес будет показывать на участок памяти, в котором хранится хрен-знает-что? И если строка по ссылке запоминается в str3, то этот адрес потом вообще не нужен. Достаточно запомнить (str3 = rec.a.s) и сохранить str3, а потом восстановить (rec.a.s := str3) и всё. Через move() можно сохранять только неуправляемые просты типы, вроде integer, cardinal, boolean, статических массивов и записей, состоящих только из таких же простых типов.
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745420
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registeredНу а как? Передать структуру, а потом её восстановить? Не по одному полю же?Ты не поверишь! Именно так и делают сериализаторы. Примеры можешь посмотреть в том-же Classes.pas
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745487
registered
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alekcvpИ если строка по ссылке запоминается в str3, то этот адрес потом вообще не нужен. Достаточно запомнить (str3 = rec.a.s) и сохранить str3, а потом восстановить (rec.a.s := str3) и всё.Так не работает. Access violation.

Код: pascal
1.
2.
move(str1[1],rec,length(str1)); // копируем структуру, затираем адрес rec.a.s
rec.a.s := str3; // AV - вероятно, он хочет освободить строку по старому адресу



Код: pascal
1.
2.
3.
4.
rec.a.s := str3; // сразу скопируем строку, выделяя новую память
p:=pointer(rec.a.s); // не @rec.a.s, а pointer(rec.a.s)
move(str1[1],rec,length(str1)); // копируем структуру
pointer(rec.a.s):=p; // восстанавливаем адрес строки
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745509
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
registeredТак не работает. Access violation.
Код: pascal
1.
2.
move(str1[1],rec,length(str1)); // копируем структуру, затираем адрес rec.a.s
rec.a.s := str3; // AV - вероятно, он хочет освободить строку по старому адресу


Именно то, о чём я говорил: вы командой Move() затираете действительный адрес с мусором (т.е. устаревшим адресом s, который сейчас содержит неизвестно что), поэтому присвоение в следующей строке вызывает ошибку. Поэтому поля записи с динамическими типами следует вообще исключить из сохранения через move() и сохранять их отдельно. И да, проще всего это сделать через сохранение каждого поля отдельно.

Ну или так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
type ta=packed record
s:string;
i:integer;
end;

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

.........
var
  str1: TBytes;
  str3: string;

{ Сохранение }
StaicSize = SizeOf(rec.a.i) + SizeOf(rec.i);
SetLength(str1, StaticSize);
Move(rec.a.i, str1[1], StaticSize);
str3 := rec.a.s;

{ Восстановление }
Move(str1[1], rec.a.i, StaticSize);
rec.a.s := str3;
...
Рейтинг: 0 / 0
Как сохранить в файл запись (record) с динамическими массивами?
    #39745529
Sapersky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Насмотревшись на ваши мучения, решил-таки выложить свой модуль для автоматического сохранения подобных структур.
Я не буду его хвалить и пиарить, это гнусное хакерство (поскольку писалось ещё до "новой" RTTI) и я сам им уже не пользуюсь - в основном потому, что не использую структуры с многоуровневой вложенностью массив-запись-массив. Всё-таки они неудобны по многим причинам.
Хотя с современными навороченными рекордами может и есть какой-то смысл.
...
Рейтинг: 0 / 0
45 сообщений из 45, показаны все 2 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как сохранить в файл запись (record) с динамическими массивами?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]