Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Александр Пекшев aka Modis от 06-12-2018, 23:18:16

Название: "Оборванные" данные в XData
Отправлено: Александр Пекшев aka Modis от 06-12-2018, 23:18:16
Всем привет. Хочу понять, как такая проблема вообще может случится и кто виноват - автокад или плагин.

Суть такова - я в примитив записываю строковые данные, которые представляют собой json. Сам json получается так:
Код - C# [Выбрать]
  1. var resultBuffer = new ResultBuffer();
  2. Dictionary<string, object> propertiesDataDictionary = new Dictionary<string, object>();
  3. // заполнение данными....
  4. using (MemoryStream stream = new MemoryStream())
  5. {
  6.     DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Dictionary<string, object>),
  7.         new DataContractJsonSerializerSettings() { UseSimpleDictionaryFormat = true });
  8.     serializer.WriteObject(stream, propertiesDataDictionary);
  9.     byte[] bytes = stream.ToArray();
  10.     string json = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
  11.     AcadHelpers.WriteMessageInDebug($"Length of json: {json.Length}");
  12.     resultBuffer.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, json));
  13. }
  14.  
  15. return resultBuffer;

Добавление в XData выглядит так:
Код - C# [Выбрать]
  1. using (var tr = AcadHelpers.Database.TransactionManager.StartTransaction())
  2. {
  3.     var ent = tr.GetObject(axis.BlockId, OpenMode.ForWrite);
  4.     ent.XData = axis.GetDataForXData();
  5.     tr.Commit();
  6. }

Результат должен быть примерно таким:
Цитировать
{"LineType":"осевая","LineTypeScale":1,"TextStyle":"Standard","MarkersPosition":"Bottom","Fracture":10,"BottomFractureOffset":0,"TopFractureOffset":0,"MarkersDiameter":10,"MarkersCount":1,"FirstMarkerType":"Type1","SecondMarkerType":"Type1","ThirdMarkerType":"Type1","BottomOrientMarkerVisible":false,"TopOrientMarkerVisible":false,"OrientMarkerVisibilityDependency":false,"OrientMarkerType":"Type1","ArrowsSize":3,"TextHeight":3.5,"FirstTextPrefix":"","FirstText":"1","FirstTextSuffix":"","SecondTextVisibility":false,"SecondTextPrefix":"","SecondText":"","SecondTextSuffix":"","ThirdTextVisibility":false,"ThirdTextPrefix":"","ThirdText":"","ThirdTextSuffix":"","BottomOrientText":"","TopOrientText":"","BottomLineAngle":0,"TopLineAngle":0,"EndPoint":"0$-642.494183297735$0","LayerName":"По умолчанию","Scale":"1:30","StyleGuid":"00000000-0000-0000-0000-000000000000"}

Да, строка длинная, но долго тестировал - проблем не было.

Сегодня мне скинули чертеж, в котором в примитиве вот такие данные:
Цитировать
{"LineType":"осевая","LineTypeScale":1,"TextStyle":"_ГОСТ","MarkersPosition":"Bottom","Fracture":10,"BottomFractureOffset":0,"TopFractureOffset":0,"MarkersDiameter":10,"MarkersCount":1,"FirstMarkerType":"Type1","SecondMarkerType":"Type1","ThirdMarkerType"

Я уточнял у пользователя - во время работы в автокаде происходила фатальная ошибка. Возможно ли такое, что ошибка произошла ровно в тот момент, когда происходила фиксация транзакции?

Пытаюсь понять, как вообще такой эффект может произойти? И можно ли его вызвать самому?
Название: Re: "Оборванные" данные в XData
Отправлено: avc от 06-12-2018, 23:39:10
Может просто кто-то прогнал Audit и обрезалось до 250 символов
Название: Re: "Оборванные" данные в XData
Отправлено: avc от 06-12-2018, 23:40:13
Ну точно - там же ровно 255
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Ривилис от 06-12-2018, 23:53:20
Суть такова - я в примитив записываю строковые данные,
Длина строки в Xdata - 255 символов. Так что если > 255, то разбивай по 255 символов. Ну и 16K на все (т.е. и твои и чужие!!!) Xdata в примитиве/объекте.
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Пекшев aka Modis от 07-12-2018, 09:06:04
Неприятно как-то. Почему Автокад позволяет положить и хранить строку свыше 255 символов, но после команды Audit режет её? Почему не резать сразу? Чтобы сразу можно было это заметить, а не вот так
И сразу вопрос про 16К на все - он сразу сигнализирует/обрежет/не даст добавить или как и со строкой - добавит, а потом порежет данные?
Название: Re: "Оборванные" данные в XData
Отправлено: Владимир Шу от 07-12-2018, 10:20:26
Александр Пекшев aka Modis, на форуме была тема посвященная этому вопросу, ссылку не дам, но помню что была и там и про ограничения и про 16К было
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Пекшев aka Modis от 07-12-2018, 12:22:56
Владимир Шу, ага нашел - вот она (http://adn-cis.org/forum/index.php?topic=8184.0). Дмитрий исследовал.
Самое забавное - ведь читал её. Но мозг - штука уникальная - забыл про это совсем. Хотя, там ответы на все мои вопросы
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Пекшев aka Modis от 07-12-2018, 12:32:32
А вот интересно - если я заменю хранение в Xdata, на хранение в XRecord (я храню одну строчку, но очень длинную), решит ли этой моей проблемы, без больших переделок? Или при работе с XRecord я могу столкнуться с чем-то подобным?
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Ривилис от 07-12-2018, 13:32:21
Или при работе с XRecord я могу столкнуться с чем-то подобным?
Разбивать на 255 символов придётся. Не будет ограничения на 16К, но потребуется еще и копировать это всё вместе с объектом, придумывать логику обработки... Не думаю, что это хороший выход.
Название: Re: "Оборванные" данные в XData
Отправлено: Дмитрий Загорулькин от 07-12-2018, 14:16:12
А вот интересно - если я заменю хранение в Xdata, на хранение в XRecord (я храню одну строчку, но очень длинную), решит ли этой моей проблемы, без больших переделок? Или при работе с XRecord я могу столкнуться с чем-то подобным?
С ограничениями - вряд ли. А вот другие трудности могут возникнуть. Например, если перетаскивается перерисованный объект. При этом часто создаётся временная копия объекта. XData в этом случае у копии будут, а вот словаря расширения - нет. Потому что словарь может быть только у объекта внутри базы данных. Так что, в этом и любых подобных случаях придётся искать сперва исходный объект, затем его словарь...
Разбивать на 255 символов придётся.
Насколько я помню, в Xrecords таких ограничений нет. Вроде где-то на болоте исследовали, что в Xrecord можно гигабайты информации помещать.
Но, для уверенности, неплохо было бы это проверить, конечно же.
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Ривилис от 07-12-2018, 14:19:23
Цитата: Александр Ривилис от 07-12-2018, 12:32:21

    Разбивать на 255 символов придётся.

Насколько я помню, в Xrecords таких ограничений нет. Вроде где-то на болоте исследовали, что в Xrecord можно гигабайты информации помещать.
Но, для уверенности, неплохо было бы это проверить, конечно же.
255 символов - это длина на один код группы:

(https://lh3.googleusercontent.com/-OJE4lOyMGmo/XApYpzDwpXI/AAAAAAAAPV0/AAa2gSZcRcg5XcnVCoUqKwjNGmosc6C8QCHMYCw/s0/clipboard.png)

Суммарно может быть очень много. До 2 Гбайт данных на XRecord.
Название: Re: "Оборванные" данные в XData
Отправлено: Дмитрий Загорулькин от 07-12-2018, 14:46:03
Значит, неправильно помню :)
Название: Re: "Оборванные" данные в XData
Отправлено: Дмитрий Загорулькин от 07-12-2018, 15:24:58
Кстати, если использовать XRecord, можно же строку перевести в байты и записать под кодом BinaryChunk. Можно даже не строку писать, а сериализовать класс с данными.
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Ривилис от 07-12-2018, 15:42:24
Кстати, если использовать XRecord, можно же строку перевести в байты и записать под кодом BinaryChunk. Можно даже не строку писать, а сериализовать класс с данными.
Только там длина еще меньше, так как BinaryChunk содержит в себе длину этой строки:
(https://lh3.googleusercontent.com/-hNTHjlCYscc/XAprG6jV56I/AAAAAAAAPWA/Imvw5gKuR-A2Wy6n12bz3NCYbjaTZgHrACHMYCw/s0/clipboard2.png)

Название: Re: "Оборванные" данные в XData
Отправлено: Дмитрий Загорулькин от 07-12-2018, 16:37:02
Эх, и тут ограничения... :)
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Пекшев aka Modis от 27-12-2018, 22:27:41
И все-же тема не исчерпана. Мне все-равно прилетают ошибки типа "Ошибка десериализации объекта типа...". Видимо хранению строк в XData нет доверия, так как там видимо можно хранить не все символы
В итоге решил оставить тот-же самый json, но записывать его под кодом 1004 - ExtendedDataBinaryChunk. Сейчас как раз переделываю. Надеюсь, что это будет последний вариант ))
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Ривилис от 27-12-2018, 23:03:00
Александр Пекшев aka Modis,
Подозреваю, что ошибка не в этом.
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Пекшев aka Modis от 27-12-2018, 23:09:25
Александр Пекшев aka Modis,
Подозреваю, что ошибка не в этом.
А если, допустим, плагин будет установлен на турецком или китайском автокаде - как тогда будут записаны данные в XData, если среди них есть имена слоёв с соответствующими символами?
Конечно, я не спорю, что ошибка может быть в чем-то другом. Изначально меня смутила такая ошибка:
Цитировать
Обнаружен непредвиденный символ "ã"
Но, к сожалению, у меня есть только ошибки сериализации и нет никакой больше информации, и нет самих документов. Придется как-то на ощупь =)
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Пекшев aka Modis от 27-12-2018, 23:11:16
Возможно причина кроется в этой строке
Код - C# [Выбрать]
  1. using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Ривилис от 27-12-2018, 23:20:39
Возможно причина кроется в этой строке
Код - C# [Выбрать]
  1. using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
Вполне возможно. Строки в AutoCAD хранятся в UNICODE (не UTF8). Поэтому никакой роли не играет язык AutoCAD/Windows.
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Пекшев aka Modis от 27-12-2018, 23:32:31
Строки в AutoCAD хранятся в UNICODE (не UTF8)
А использование DataContractJsonSerializer требует кодировки в UTF8. Хотя, может и не требует, но на MSDN в примере присутствует кодировка. Не люблю все эти кодировки ((
В общем - я сделал вспомогательный класс, в котором всего одно поле, хранящее строку, представляющую собой json. По известному примеру (https://adndevblog.typepad.com/autocad/2012/05/serialize-a-net-class-into-an-autocad-drawing-database.html) записываю в XData экземпляр класса. Правда при десериализации приходится сначала получить экземпляр этого класса, а потом строку перегнать в MemoryStream, ибо DataContractJsonSerializer, зараза, десириализует из потока...
Короче - добавил костыль =)) Можно было бы проще, но придется другие места переделывать, плюс "поддержка обратной совместимости" - сначала пробую почитать по старому из строк, а потом уже по новому - из байт.
Буду следить/тестировать дальше как пойдет
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Ривилис от 27-12-2018, 23:40:07
А использование DataContractJsonSerializer требует кодировки в UTF8.
А ты попробуй Encoding.Unicode. Впрочем, конечно какие-то символы в строке могут интерпретироваться не так. Например, "\M+XXXXXX", "\U+XXXX"
Название: Re: "Оборванные" данные в XData
Отправлено: Александр Пекшев aka Modis от 27-12-2018, 23:43:28
А ты попробуй Encoding.Unicode
Я пока писал предыдущий ответ вдруг осознал, что мне json'а вообще не понадобится =)) Уже переделал свой код. Правда пока оставил старый вариант чтение из строковых значений с десириализацией в json, но как-только пользователи обновятся, то уберу и его совсем. По идее проблем с кодировками вообще не будет