Ошибки PascalABC.NET

Да, лажа имеет место быть.

Более того, ошибка катастрофическая. Для тестирования был сформирован файл из четырех чередующихся записей с длиной строки 5 и 255 символов. Иными словами, приведенное выше содержимое было повторено дважды.

Ниже приведены результаты чтения в типизированный файл.

  1. последовательное чтение.
(10,*****,11) 5
(20,***************************************************************************************************************************************************************************************************************************************************************,21) 255
(10,*****,11) 5
(20,***************************************************************************************************************************************************************************************************************************************************************,21) 255
  1. чтение с подводом seek в порядке 0, 1, 2, 3.
(10,*****,11) 5
(20,***************************************************************************************************************************************************************************************************************************************************************,21) 255
(2560,,2816) 0
(5120,,1387050) 0

Хорошо видно, что начиная со второй записи пошла ошибка.

Резюме: грубая ошибка, требуется исправление.

Использованные программы тут: Errors.rar (920 Байт)

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

Я вот уже даже и не знаю. С одной стороны - исправлять не нужно, так как это сожмёт полезные возможности. С другой - те, кому нужна гибкость, будут использовать напрямую средства .NET и от ограничений типизировпнных файлов им ни тепло ни холодно. Тогда исправлять нужно. А то что сейчас - это безобразие, согласен. Между двух стульев.

Будет это исправляться, если будет - как и кем - это уже к разработчикам. Повторю суть ошибки: при работе с типизированным файлом, если в структуре записи есть символьные поля с длиной более 127 байт и реальное содержимое этих полей в записях может иметь длину как от 0 до 127 байт, так и более 127 байт, типизированный файл формируется некорректно. Он перестает быть совместимым с более ранними версиями Паскаль и даже с PascalABC. Полученный файл корректно читается последовательным доступом, но в прямом доступе (с поиском записей по Seek) работа фактически невозможна из-за ошибочного подвода записей.

2 лайка

Потому что реализовывать более гибкое сохранение надо отдельно, а не поверх типизированых файлов, у которых структуру уже утвердили несколько десятков лет назад.

А давайте сперва определился, нужны ли они нам? Может и исправлять ничего не надо.

Да. Совместимость.

Вот объясните мне, пожалуйста, такую вещь. Если взять любой исходник, скажем, на Дельфи, то там будут подключаться совершенно другие библиотеки, которых нет в Паскале. Взять например формы. Там всё другое. PascalABC.NET и другие паскали - это как C/C++ и C#. Внешне похожи, но при первой же попытке их взаимной замены голова будет разбита о массу ошибок, неоднозначностей и различий.

Есть вариант: расписаться в собственном бессилии и где-то в Справке указать, что в типизированных файлах нельзя использовать строки длиной более 127 байт.

Так. Я уже запутался :smile: Вот Вы лично в каком виде хотите видеть типизированные файлы?

Ну вы загнули, это ещё хуже чем костылём исправлять)))

2 лайка

Лично я - в таком, в каком они во всех Паскалях. В каноническом, с короткими строками. Потому что любое отклонение от этого повлечет за собой 1) потерю совместимости с файлами, полученными в других паскалях 2) либо жуткую неэффективность работы с seek, либо это будут уже не паскалевские типизированные файлы.

2 лайка

Ну что ж. Я, пожалуй, соглашусь. Приводим типизированные файлы к их стандартному виду.

1 лайк

Пока то, что предлагают @Gleb и @Sun_Serega - это, в основном, четвертый тип файлов, которого в Паскале нет. Захотят его разработчики добавить - да ради бога!

В конце концов, в IBM System\370 (а это было три с лишним десятка лет назад) только на уровне операционной системы было пять методов доступа к файлам - BSAM, BDAM, BPAM, ISAM, VSAM, а уж сколько разновидностей предлагал язык PL/1 - так и перечислять устанешь.

А вот для этого нужно подождать явления народу @Admin, который трижды стукнет посохом в пол и возвестит: “НЕ БУДЕМ МЫ ЭТОГО ДЕЛАТЬ!” :smile: Ну, … или не возвестит. А тогда ломать голову над названиями.

1 лайк

Да зачем, вообще, ради 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 (убрав ограничение “только записи без ссылочных полей” и немного подправив) - это должно работать.

1 лайк

Можно и так. Только смысл в этом немного иной. В типизированом файле все элементы имеют один тип(следует из названия), а то, что предлагаете Вы - это нетипизированный файл. Туда можно так добавлять. Единственное, как это можно задать - 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, которые могут и приватные поля сохранять.