Более того, ошибка катастрофическая.
Для тестирования был сформирован файл из четырех чередующихся записей с длиной строки 5 и 255 символов. Иными словами, приведенное выше содержимое было повторено дважды.
Ниже приведены результаты чтения в типизированный файл.
Можно конечно исправить костылём, но я готов помочь исправить по нормальному. Так чтоб сразу и читаться стало блоками а не по 1 полю. По крайней мере я разобрался во всех кишках, как что работает, поэтому знаю что именно надо изменить.
Я вот уже даже и не знаю. С одной стороны - исправлять не нужно, так как это сожмёт полезные возможности. С другой - те, кому нужна гибкость, будут использовать напрямую средства .NET и от ограничений типизировпнных файлов им ни тепло ни холодно. Тогда исправлять нужно. А то что сейчас - это безобразие, согласен. Между двух стульев.
Будет это исправляться, если будет - как и кем - это уже к разработчикам. Повторю суть ошибки: при работе с типизированным файлом, если в структуре записи есть символьные поля с длиной более 127 байт и реальное содержимое этих полей в записях может иметь длину как от 0 до 127 байт, так и более 127 байт, типизированный файл формируется некорректно. Он перестает быть совместимым с более ранними версиями Паскаль и даже с PascalABC. Полученный файл корректно читается последовательным доступом, но в прямом доступе (с поиском записей по Seek) работа фактически невозможна из-за ошибочного подвода записей.
Потому что реализовывать более гибкое сохранение надо отдельно, а не поверх типизированых файлов, у которых структуру уже утвердили несколько десятков лет назад.
Вот объясните мне, пожалуйста, такую вещь. Если взять любой исходник, скажем, на Дельфи, то там будут подключаться совершенно другие библиотеки, которых нет в Паскале. Взять например формы. Там всё другое. PascalABC.NET и другие паскали - это как C/C++ и C#. Внешне похожи, но при первой же попытке их взаимной замены голова будет разбита о массу ошибок, неоднозначностей и различий.
Есть вариант: расписаться в собственном бессилии и где-то в Справке указать, что в типизированных файлах нельзя использовать строки длиной более 127 байт.
Лично я - в таком, в каком они во всех Паскалях. В каноническом, с короткими строками. Потому что любое отклонение от этого повлечет за собой 1) потерю совместимости с файлами, полученными в других паскалях 2) либо жуткую неэффективность работы с seek, либо это будут уже не паскалевские типизированные файлы.
Пока то, что предлагают @Gleb и @Sun_Serega - это, в основном, четвертый тип файлов, которого в Паскале нет. Захотят его разработчики добавить - да ради бога!
В конце концов, в IBM System\370 (а это было три с лишним десятка лет назад) только на уровне операционной системы было пять методов доступа к файлам - BSAM, BDAM, BPAM, ISAM, VSAM, а уж сколько разновидностей предлагал язык PL/1 - так и перечислять устанешь.
А вот для этого нужно подождать явления народу @Admin, который трижды стукнет посохом в пол и возвестит: “НЕ БУДЕМ МЫ ЭТОГО ДЕЛАТЬ!” Ну, … или не возвестит. А тогда ломать голову над названиями.
Да зачем, вообще, ради 1 метода создавать отдельный тип. Можно ведь просто добавить метод вроде WriteComplexObject в тип file. Вроде - ничего не ломается. Более того, тогда можно делать так, без каких то опасений:
type
t1=class
public x:real;
public s:string;
end;
begin
var f:file;
Rewrite(f,'temp.bin');
var a := new t1;
a.x := 123.456;
a.s := 'abc';
f.WriteComplexObject(a);
f.Close;
Reset(f);
Read(f,a.x);
Read(f,a.s);
f.Close;
end.
Если текущую реализацию file of T перенести в WriteComplexObject (убрав ограничение “только записи без ссылочных полей” и немного подправив) - это должно работать.
Можно и так. Только смысл в этом немного иной. В типизированом файле все элементы имеют один тип(следует из названия), а то, что предлагаете Вы - это нетипизированный файл. Туда можно так добавлять. Единственное, как это можно задать - file of <type>. Но вот насколько я знаю, в один файл при сериализации можно записать только один объект. В таком случае, думаю, есть смысл вводить не аналог типизированного файла, а встроенные методы сериализации в файл и десериализации. Это было бы логичнее. Например так:
Type a = class
End;
Begin
var obj := new a();
serialize(obj, 'object.bin');
var newObj := deserialize('object.bin')!
End.
Ну так правильно, я же сейчас не про типизированные файлы говорю, а как раз про тот четвёртый тип, который вы никак назвать не могли. И да, это по сути что то вроде десериализации, но смысл в том, чтоб можно было запихнуть несколько объектов разных стилей и чтоб работало это в стиле паскаля. То есть программист знает что сначала в файле идёт переменная типа integer, потом record1, а потом real. В этом порядке записывает в файл через переменную типа file (безтиповый файл, тот что без of T), и в том же порядке считывает. Это уже так же можно делать, но только с простейшими типами вроде real или byte.
Нет, можно получить поля (только публичные) любого класса или записи в виде последовательности, программно:
type
t1=class
public поле1:real;
public field2:byte;
end;
begin
var a := new t1;
var t := a.GetType;
var fields := t.GetFields;
fields
.Select(fld->(fld.Name,fld.FieldType))
.PrintLines;
end.
Кроме того, есть виды сериализации вроде XML, которые могут и приватные поля сохранять.