Динамический массив в файл и обратно

Необходимо динамический массив типа array of array of array of integer сохранить в файл, и потом прочитать его в переменную такого же типа. Что можно сделать? Есть стандартные решения из библиотек?

Спасибо

Если без лишних телодвижений, то я бы в json сериализовал каким-нибудь Newtonsoft.Json

Ну, BinaryWriter/BinaryReader

begin
  var ms := new System.IO.MemoryStream(1000);
  var bw := new System.IO.BinaryWriter(ms);
  var a: array of array of array of integer := |||1,2,3|,|4,5,6||,||7,8,9|,|10,11,12|||;
  bw.Write(a.Length);
  for var i := 0 to a.Length - 1 do
    begin
      bw.Write(a[i].Length);
      for var j := 0 to a[i].Length - 1 do
        begin
          bw.Write(a[i, j].Length);
          for var k := 0 to a[i, j].Length - 1 do
          begin
            bw.Write(a[i, j, k]);
          end;
        end;
    end;
  System.IO.File.WriteAllBytes('array.dat', ms.ToArray());
  ms := new System.IO.MemoryStream(System.IO.File.ReadAllBytes('array.dat'));
  var br := new System.IO.BinaryReader(ms);
  var a2: array of array of array of integer;
  var len := br.ReadInt32();
  SetLength(a2, len);
  for var i := 0 to a2.Length - 1 do
    begin
      len := br.ReadInt32();
      SetLength(a2[i], len);
      for var j := 0 to a2[i].Length - 1 do
        begin
          len := br.ReadInt32();
          SetLength(a2[i, j], len);
          for var k := 0 to a2[i, j].Length - 1 do
          begin
            a2[i, j, k] := br.ReadInt32();
          end;
        end;
    end;
  
end.
1 лайк

С подпрограммами чище даже когда размер кода это не уменьшает:

## uses System.IO;

procedure WriteArr<T>(self: BinaryWriter; a: array of T; write_item: (BinaryWriter,T)->()); extensionmethod;
begin
  self.Write(a.Length);
  foreach var x in a do
    write_item(self, x);
end;
function ReadArr<T>(self: BinaryReader; read_item: BinaryReader->T): array of T; extensionmethod :=
  ArrGen(self.ReadInt32, i->read_item(self));

var a := |||1,2,3|,|4,5,6||,||7,8,9|,|10,11,12|||;
var fname := 'a.bin';

begin
  var f := &File.Create(fname);
  BinaryWriter.Create(f)
    .WriteArr(a, (bw,a)->
    begin
      bw.WriteArr(a, (bw,a)->
      begin
        bw.WriteArr(a, (bw,x)->
          bw.Write(x)
        )
      end)
    end);
  f.Close;
end;

begin
  var f := &File.OpenRead(fname);
  Println(
    BinaryReader.Create(f)
      .ReadArr(br->br
        .ReadArr(br->br
          .ReadArr(br->br
            .ReadInt32
          )
        )
      )
  );
  f.Close;
end;

Вы, кстати, уверены что вам нужно именно array of array of array of integer (массив массивов массивов) а не array[,,] of integer (3-х мерный массив)? Такая вложенность редко бывает оправдана…

Спасибо за исчерпывающий ответ. Неожиданно получить ответ в готовом виде. Специально писали?

:+1:

Спасибо за важное дополнение

Да, уверен, это оправдано. В массиве [, ,] будет избыточность объема перед вложенностью, где каждый индекс содержит уже обработанную информацию.

Довольно часто избыточность хранения данных - невысокая плата за удобство работы с ними.

1 лайк

В таком случае обычно стоит объявить свои типы данных для каждого уровня вложенности массива и инкапсулировать работу с ними.

Вы имеете в виду для читабельности? Или какие то другие соображения?

И для масштабируемости

Да, Вы правы. Но я на пределе оперативки. Приходится хранить только нужную информацию.

Соображения те же, по которым я изменил код от ibond-а, добавив подпрограммы.

Масштабируемость и читабельность это только некоторые из плюсов. Но в общем случае - разбиение сложной структуры данных на несколько простых увеличивает модульность кода.

Кроме тех 2 плюсов, к примеру, после разбиения на:

SmallThing = record
  a: array of integer;
end;
MediumThing = record
  a: array of SmallThing;
end;
LargeThing = record
  a: array of MediumThing;
end;

И объявления конструктора и методов в этих типах - вы можете очень легко использовать MediumThing напрямую, если окажется что где то надо на 1 уровень вложенности меньше. Или наоборот, если надо на 1 уровень больше - не надо делать дубли кода или ещё сильнее усложнять обрабатывающий код.

Согласен, так удобнее. Кроме, возможно, одного нюанса, если нужно узнать структуру LargeThing, придется отматывать назад к MediumThing, а потом к SmallThing.

Это работает!

Спасибо Вам.

У меня этой проблемы ни разу не возникало с тех пор, как я поставил на компьютер 64 Гб оперативки.

Пока не возникла необходимость найти результат попарных комбинаций двух массивов по 10.000.000 ячеек :wink:

1 лайк

Я только сейчас увидел, что мне отвечает автор учебника по PABC. Ваша книга постоянно открыта. Я по ней учусь. Стараюсь соответствовать в меру способностей.

С уважением

1 лайк

Это не учебник, скорее справочник, причем по достаточно старой версии 3.5. Но достаточно глубокий. Менее глубоки, но зато постоянно актуальны сведения из этого учебного курса