Прочитать текстовый файл из временного хранилища

1. LosevI 21.04.21 03:52 Сейчас в теме
Здравствуйте. На Клиенте с помощью предназначенного для этого метода происходит интерактивный выбор файла XML пользователем (по сути это текстовый файл), файл записывается во временное хранилище.

Затем на сервере значение из временного хранилища необходимо получить в виде строки-содержимого.
В данный момент использую следующий код:
ДвоичныеДанныеКонтейнера = ПолучитьИзВременногоХранилища(ПараметрыАдресФайла);
Если ДвоичныеДанныеКонтейнера = Неопределено Тогда
	ТекстОшибки = "Не удалось прочитать файл с контейнером.";
Иначе
	Попытка
		ЧтениеДанных = Новый ЧтениеДанных(ДвоичныеДанныеКонтейнера);
		ЧтениеДанных.КодировкаТекста = КодировкаТекста.UTF8;
		ЧтениеТекста = Новый ЧтениеТекста(ЧтениеДанных.ИсходныйПоток(), КодировкаТекста.UTF8);
		СтрокаXML = ЧтениеТекста.Прочитать();
		ЧтениеТекста.Закрыть();
		ЧтениеДанных.Закрыть();
	Исключение
		ТекстОшибки = "Не удалось получить строку XML из файла.";
	КонецПопытки;
КонецЕсли;
Показать


1) Является ли этот код оптимальным и правильным для поставленной задачи на современных платформах?
2) Есть ли способ решить подобную задачу на платформах до 8.3.9, в которых объект ЧтениеДанных отсутствовал?
По теме из базы знаний
Найденные решения
2. nomad_irk 72 21.04.21 06:08 Сейчас в теме
(1)
1. Правильным - да, оптимальным - нет, т.к. происходит чтение всего файла XML в ОЗУ.
2. Как-то так:

ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
ДвоичныеДанныеКонтейнера = ПолучитьИзВременногоХранилища(ПараметрыАдресФайла);

ДвоичныеДанныеКонтейнера.Записать(ИмяВременногоФайла);

Поток = Новый ЧтениеXML;
Поток.Открыть(ИмяФайла);

Пока Поток.Прочитать() Цикл
        Пока Поток.ТипУзла = ТипУзлаXML.НачалоЭлемента И Поток.Имя = "НужноеИмяТэгаОбъекта" Цикл 
            ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(Поток);
            ..............
        КонецЦикла;
КонецЦикла;
Поток.Закрыть();
УдалитьФайлы(ИмяВременногоФайла);

Показать
LosevI; mashtak; BomjBandit; vadim.semyonov.rzn; +4 Ответить
16. spacecraft 22.04.21 05:50 Сейчас в теме
(14) через ДиалогВыбораФайла можно получить имя файла и прочитать
Режим = РежимДиалогаВыбораФайла.Открытие;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = "";
Фильтр = "Файл xml|*.xml";
ДиалогОткрытияФайла.Фильтр = Фильтр;
ДиалогОткрытияФайла.Заголовок = "Выберите файл";
Если ДиалогОткрытияФайла.Выбрать() Тогда
    ИмяФайла = ДиалогОткрытияФайла.ПолноеИмяФайла;
    Чтение = Новый ЧтениеТекста(ИмяФайла);
	Текст = Чтение.Прочитать();
	НужнаяПроцедураНаСервере(Текст);
Иначе
    Предупреждение("Файл не выбран!");
КонецЕсли;
Показать

Но да, на веб клиенте не доступно, но и в (1) про него не упоминалось.
Тогда для веб клиента можно на сервере читать через ЧтениеТекста вместо ЧтениеДанных.
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. nomad_irk 72 21.04.21 06:08 Сейчас в теме
(1)
1. Правильным - да, оптимальным - нет, т.к. происходит чтение всего файла XML в ОЗУ.
2. Как-то так:

ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
ДвоичныеДанныеКонтейнера = ПолучитьИзВременногоХранилища(ПараметрыАдресФайла);

ДвоичныеДанныеКонтейнера.Записать(ИмяВременногоФайла);

Поток = Новый ЧтениеXML;
Поток.Открыть(ИмяФайла);

Пока Поток.Прочитать() Цикл
        Пока Поток.ТипУзла = ТипУзлаXML.НачалоЭлемента И Поток.Имя = "НужноеИмяТэгаОбъекта" Цикл 
            ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(Поток);
            ..............
        КонецЦикла;
КонецЦикла;
Поток.Закрыть();
УдалитьФайлы(ИмяВременногоФайла);

Показать
LosevI; mashtak; BomjBandit; vadim.semyonov.rzn; +4 Ответить
3. starik-2005 3036 21.04.21 12:05 Сейчас в теме
(2) Этот вариант тоже читает файл в память - метод получения двочиных данных.

Вообще, если делать быстро, то надо вообще вот так делать (при файлах не очень большого размера):
Код
&НаКлаенте
Процедура ОбработатьКлиент(ИмяФайла)
  ОбработатьСервер( Новый ДвоичныеДанные( ИмяФайла ) );
КонецПроцедуры

Процедура ОбработатьСервер( ДД )
  Поток = Новый ПотокВПамяти ( ДД );
  ЧтениеХМЛ = Новый ЧтениеХМЛ( Поток );
  // какое-то шаманство
  ЧтениеХМЛ.Закрыть();
КонецПроцедуры
Показать полностью
Ну все слова в синтаксис-помощнике подглядеть труда не составит...
dynamicsystems; +1 Ответить
4. herfis 498 21.04.21 12:29 Сейчас в теме
(3) Это был вариант для старых релизов. Там ключевое - предварительное сохранение файла на диск.
9. starik-2005 3036 21.04.21 13:16 Сейчас в теме
(4)
вариант для старых релизов
Ну так можно просто сохранить, потом ДД = ""; - все, память очистили. Потом прочитать из файла уже по старорежжимному...
5. nomad_irk 72 21.04.21 12:36 Сейчас в теме
(3) в первом случае файл целиком читается в ОЗУ, а в случае, что описал я - нет, в этом принципиальное отличие подходов.

Если чтение в виде двоичных данных можно делать как-то частями и при этом прочитанную часть можно обработать, то делать нужно именно так.
7. starik-2005 3036 21.04.21 13:03 Сейчас в теме
(5) А это:
ДвоичныеДанныеКонтейнера = ПолучитьИзВременногоХранилища(ПараметрыАдресФайла);

ДвоичныеДанныеКонтейнера.Записать(ИмяВременногоФайла);


Это не чтение файла целиком в ОЗУ? Двоичные данные контейнера что содержат?
При получении на сервере значения из временного хранилища следует учитывать то, что оно получается по ссылке. В действительности, ссылка эта указывает на значение, которое хранится в кеше. В течение 20 минут, с момента помещения в хранилище или же с момента последнего обращения, значение сохранится в кеше, а затем записывается на диск и из кеша удаляется. При следующем обращении значение загружается с диска и снова помещается в кеш.

Фактически, кеш - это память, которая через 20 минут выгрузится на диск. При варианте с двоичными данными, передаваемыми на сервер, память экономится только на клиенте.
10. nomad_irk 72 21.04.21 14:08 Сейчас в теме
(7)хорошо. Убираем помещение ДД во ВрХр и получение из него - читаем XML и формируем ОбъектXDTO прямо на клиенте.
11. starik-2005 3036 21.04.21 15:25 Сейчас в теме
(10)
ОбъектXDTO прямо на клиенте
В принципе даже работает, но не все. Объект XDTO - это тоже все в памяти, поэтому лучше последовательно читать, особенно если файл большой. По крайней мере результат вебсервиса - объект тот самый - не ездит между сервером и клиентом, ну и веб-сервисы на клиенте не работают.

Если файло большое, то совсем правильно читать его и скармливать фоновым заданиям прочитанное (по сотне единиц, например).
12. nomad_irk 72 21.04.21 15:37 Сейчас в теме
(11)Я ж привел пример чтения по одному ОбъектXDTO - он занимает минимально возможное для своего существования место в ОЗУ.

А вот х.з., можно будет ОбъектXDTO, сформированный на клиенте передать на сервер или нет :)
13. starik-2005 3036 21.04.21 16:01 Сейчас в теме
(12) впринципе, для объекта XDTO у 1С есть своя модель данных в базовых пакетах, т.е. он вроде как сериялизуется, а все, что сериализуется, может ездить туды-сюды, если там и сям доступно.
6. spacecraft 21.04.21 12:59 Сейчас в теме
(1)
На Клиенте с помощью предназначенного для этого метода происходит интерактивный выбор файла XML пользователем (по сути это текстовый файл), файл записывается во временное хранилище.

(1)
Есть ли способ решить подобную задачу на платформах до 8.3.9, в которых объект ЧтениеДанных отсутствовал?

Можно на клиенте читать не двоичные данные, а сразу текст (ЧтениеТекста) и его передавать.
14. LosevI 22.04.21 03:17 Сейчас в теме
(6) Я понял идею, но не понял реализацию, уточните пожалуйста. ЧтениеТекста получает файл по пути в системе, а не выбирает его интерактивно, кроме того, оно недоступно на веб-клиенте. Методы для работы с файловой системой (такие как НачатьПомещениеФайлаНаСервер) все и во всех платформах помещают файл в виде двоичных данных во временное хранилище.
16. spacecraft 22.04.21 05:50 Сейчас в теме
(14) через ДиалогВыбораФайла можно получить имя файла и прочитать
Режим = РежимДиалогаВыбораФайла.Открытие;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = "";
Фильтр = "Файл xml|*.xml";
ДиалогОткрытияФайла.Фильтр = Фильтр;
ДиалогОткрытияФайла.Заголовок = "Выберите файл";
Если ДиалогОткрытияФайла.Выбрать() Тогда
    ИмяФайла = ДиалогОткрытияФайла.ПолноеИмяФайла;
    Чтение = Новый ЧтениеТекста(ИмяФайла);
	Текст = Чтение.Прочитать();
	НужнаяПроцедураНаСервере(Текст);
Иначе
    Предупреждение("Файл не выбран!");
КонецЕсли;
Показать

Но да, на веб клиенте не доступно, но и в (1) про него не упоминалось.
Тогда для веб клиента можно на сервере читать через ЧтениеТекста вместо ЧтениеДанных.
8. SlavaKron 21.04.21 13:11 Сейчас в теме
Действительно, если вся задача – это получить СтрокаXML на сервере, то достаточно передать строку в параметрах серверной процедуры, минуя и временное хранилище и объекты работы с данными.
starik-2005; +1 Ответить
15. LosevI 22.04.21 03:19 Сейчас в теме
(8) Это было бы прекрасно, только расскажите мне как интерактивно выбрать файл на клиенте и получить из него строку-содержимое тоже на клиенте, с учетом поддержки всех видов клиента (см. ответ (14)).
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот