OneScript icon indicating copy to clipboard operation
OneScript copied to clipboard

ЧтениеДанных.ПрочитатьСтроку() некорректное поведение

Open ilyabaztard opened this issue 4 years ago • 7 comments

Опишите ошибку Функция ЧтениеДанных.ПрочитатьСтроку некорректно извлекает строки из двоичных данных

Воспроизведение ошибки

  1. Запустить код
ДвДанные = ПолучитьДвоичныеДанныеИзHexСтроки("31 32 33 0d 0a 34 35 36");

Чтение = Новый ЧтениеДанных(ДвДанные);

лСтрока = Чтение.ПрочитатьСтроку();
лПозиция = Чтение.ИсходныйПоток().ТекущаяПозиция();
Сообщить("Прочитана строка: " + лСтрока);
Сообщить("Текущая позиция чтения потока: " + лПозиция);

лСтрока = Чтение.ПрочитатьСтроку();
лПозиция = Чтение.ИсходныйПоток().ТекущаяПозиция();
Сообщить("Прочитана строка: " + лСтрока);
Сообщить("Текущая позиция чтения потока: " + лПозиция);

Чтение.Закрыть();
  1. Результат выполнения кода
Прочитана строка: 123
Текущая позиция чтения потока: 8
Прочитана строка:
Текущая позиция чтения потока: 8

Ожидаемый результат выполнения кода

Прочитана строка: 123
Текущая позиция чтения потока: 5
Прочитана строка: 456
Текущая позиция чтения потока: 8

Окружение

  • ОС: Win 10 pro 1909
  • Версия: oscript 1.7.0

Дополнительная информация Функция ЧтениеДанных.ПрочитатьСтроку при первом вызове корректно определяет позицию окончания первой строки корректно извлекает и возвращает первую строку НО после вызова текущая позиция чтения потока оказывается в конце потока и следующий вызов уже ничего не возвращает В 1С этот код отрабатывает как ожидается

ilyabaztard avatar Nov 17 '21 13:11 ilyabaztard

По документации, если в конструкторе ЧтениеДанных не указан разделитель строк, то его значение по умолчанию Неопределено, что даёт после инициализации РазделительСтрок="". Соответственно, КонвертируемыйРазделительСтрок по умолчанию равен "\r\n". Тогда в приведённом примере прочитанная строка должна быть "123\n456", а позиция в потоке = 8. Получается, что неправы оба: и Onescript, и 1С. Onescript читает первую строку как "123\r". Там ошибочно по умолчанию РазделительСтрок = "\n". Поток читается до конца. В 1С согласно описанию будет РазделительСтрок = "". Но в случае, когда разделитель строк - пустая строка (в т. ч. явно заданная через параметр!) как разделитель будет использована любая найденная из строк "\r", "\n","\r\n". Ошибка или в документации, или в реализации.

Mr-Rm avatar Nov 17 '21 17:11 Mr-Rm

КонвертируемыйРазделительСтрок по умолчанию равен "\r\n". Это байты 0d 0a, что вы видите в приведенном примере на позициях 3 и 4. 1С отработал корректно и документация в порядке. Onescript работает странно. Если он прочитал поток до конца, то и выводил бы содержимое всего потока. Если он прочитал только до символа \n, то позиция должна остаться 5, чтобы была возможность чтения следующей строки.

ilyabaztard avatar Nov 17 '21 19:11 ilyabaztard

Странность работы Onescript подтверждается. Но, для уточнения корректности документации и работы 1С, пример. Согласно имеющемуся описанию, какие строки должны быть прочитаны и каковы будут при этом позиции в потоке для такого варианта:

ДвДанные = ПолучитьДвоичныеДанныеИзHexСтроки("0a 0a 0d 0a 0d 0d 0d 0a");
Чтение = Новый ЧтениеДанных(ДвДанные,,, "",""); // оба разделителя - пустые строки
Пока Не Чтение.ЧтениеЗавершено Цикл
    лСтрока = Чтение.ПрочитатьСтроку();
    лПозиция = Чтение.ИсходныйПоток().ТекущаяПозиция();
    Сообщить("Прочитана строка '" + лСтрока+"' длины "+СтрДлина(лСтрока));
    Сообщить("Текущая позиция чтения потока: " + лПозиция);
КонецЦикла;
Чтение.Закрыть();

?

Mr-Rm avatar Nov 17 '21 21:11 Mr-Rm

АПИ работы с двоичными данными в 1Скрипт появилось довольно поздно, поскольку в 1С его вообще не было никакого. Подводные камни и нюансы работы 1С с ЧтениемДанных никем досконально не исследовались, в силу отсутствия опыта работы с ЧтениемДанных (его не было ни у кого на момент выхода этого АПИ). @ilyabaztard если вы окажете нам помощь и зафиксируете требования к правильному поведению - мы будем вам признательны. А за исправление вообще расцелуем и обнимем

EvilBeaver avatar Nov 18 '21 06:11 EvilBeaver

Попробую для начала доработать тесты под этот случай

ilyabaztard avatar Nov 18 '21 09:11 ilyabaztard

@ilyabaztard есть успехи?

EvilBeaver avatar Apr 13 '22 07:04 EvilBeaver

ЧтениеДанных, по-видимому, унаследовало параметры РазделительСтрок и КонвертируемыйРазделительСтрок от объекта ЧтениеТекста. Но работа с ними: значения по умолчанию и порядок применения - существенно различаются. Функции ЧтениеДанных.ПрочитатьСтроку() и ЧтениеТекста.ПрочитатьСтроку() могут давать разный результат на одинаковых входных данных с одинаковыми (в том числе явно указанными) параметрами.

Mr-Rm avatar Jun 05 '22 17:06 Mr-Rm