Часть 3
Как я автоматизировал доставку аудиоподкастов на свой плеер

Продолжение статьи про новости — как я скачиваю подкасты. Предыдущие части тут и тут.
Каждый человек выбирает себе способ, каким занимать своё свободное время. Кто-то пьёт пиво на диване и смотрит телек. Кто-то читает бумажные или электронные книги. Кто-то слушает аудио-книги и подкасты. У каждого способа есть плюсы и минусы.
У аудиокнижек и подкастов плюс в том, что можно эффективно занять время, когда держать книгу в руках просто неудобно — путь пешком до метро, беговая дорожка или другие способы активного время провождения.
Я прошёл долгий путь по выбору конкретного аудиопроигрывателя (и, возможно, этот путь ещё не закончен) — bluetooth-наушники в связке со смартфоном, наушники со встроенным плеером, и прочее и прочее. Сейчас у меня есть простенький китайский mp3-плеер (которых было заказано сразу несколько штук и в случае поломок можно просто выкинуть один и взять другой). Цена вопроса — около 300 рублей за штуку. Если плеер проработает хотя бы 1 год, то это просто удача. В моём случае один плеер работает уже с декабря 2019, что я считаю, признак успеха китайской промышленности.

В жизни, конечно, мой плеер выглядит более убого и непрезентабельно, тем не менее он работает и свои функции выполняет.
Мне очень « зашли » подкасты радио Маяк. В школе я не любил историю — все эти сухие даты, непонятные события (когда алая Роза напала на Белую Розу или наоборот? и чем вообще эта буза закончилась?). Но сейчас мне эта тема почему-то стала интересна, особенно если тему раскрывает интересный рассказчик. История страны, история мира. Интересны подкасты про общее развитие, про новые технологии. Аудио-книги, которые в своё время не успел прочитать. Всё очень интересно. И очень удобно.
Кстати, буду признателен, если в комментариях оставите ссылки на свои подкасты.
Задача: Хочется скачивать аудиофайлы с сайта радио Маяк, и раскладывать их по каталогам, чтобы потом в дальнейшем легко копировать на плеер.
Для начала посмотрим, что же пишется в файле новостей из радио Маяк. Возьмём для примера подкаст «30 сюжетов цивилизации»:

Как видим, у каждой новости (одна новость = одна радио-передача = rss.channel.item) есть тэг enclosure с гиперссылкой (атрибут url) на mp3-файл. Это именно то, что нам нужно.
Надо скачать все файлы и сохранить их на диске, сохраняя структуру папок, чтобы потом скопировать на плеер.
Не помешает база данных. Что бы использовать? Я для себя выбрал 1С — там встроенная база данных (как в MS Access), есть работа с интернетом (загрузка файлов), парсинг xml, работа с файловой системой, можно буквально мышкой нарисовать интерфейс — и всё это «из коробки»! Плюс у меня есть некоторый опыт работы с 1С.
У 1С есть бесплатный вариант (версия «для обучения программированию»), которую можно бесплатно и без смс скачать с сайта (http://online.1c.ru/catalog/programs/program/28765768/) — это свежая версия на текущий момент. Для загрузки потребуется только емейл.
У версии «для обучения программированию» есть ограничения по количеству записей в таблицах. Но это не проблема — вместо одной большой базы данных можно создать несколько маленьких.
По лицензионному соглашению мы можем использовать «версию для обучения», как ни странно, только для обучения, а не для реального учёта. Ну мы же и будем учиться?
Итак, я скачал версию 1С «для обучения программированию»…
Опустим процесс инсталляции. Там всё просто.
Почти по аналогии с MS Access (где одна база = один файл), В 1С одна база = один каталог. При запуске 1С надо будет указать какой-то каталог в качестве каталога нужной базы данных. После этого можно нажать «Конфигуратор», чтобы открыть IDE для редактирования кода и интерфейса.

Информационная база 1С состоит, грубо говоря, из непосредственно данных и из метаданных. Метаданные — код на языке 1С, описание интерфейса и прочая информация.
Можно хранить данные и метаданные в системе баз данных (MS SQL, Postgres), но 1С умеет работать и с локальной базой данных (формат 1С). Локальная файловая база данных 1С — это один файл с фиксированным именем «1Cv8.1CD», который лежит в заданном каталоге. Версия для обучения позволяет работать только с файловой базой, прикрутить Postgres к ней не получится.
Таблицы баз данных (в терминологии систем баз данных) в 1С будут называться «Справочниками» (условно постоянная информация), «Документами» (информация об изменении данных), всякими «Регистрами сведений», «Регистрами накоплений», «Регистрами бухгалтерии» (непосредственно значения изменённых данных).

Для моих целей нужно будет создать:
-
справочник «Подкасты», где хранится список интересных мне подкастов с URL на всю RSS-ленту новостей этого подкаста;
-
справочник «Аудиоматериалы», где хранятся URL на конкретные файлы MP3;
-
регистр сведений «ГлобальныеНастройки», где хранятся прочие настройки, например корневой каталог в файловой системе, куда скачивать mp3-файлы.
Формы для ввода данных для этих справочников рисуются буквально мышкой.
Вот, например, настроенный внешний вид справочника «Подкасты» (ни строчки кода!):

Если форму не рисовать, то платформа 1С сама её создаст, «на лету». Собственно, форма ввода для справочника «Подкасты» — единственная, которую я делал сам, «ручками». Остальные формы ввода платформа 1С генерирует автоматически.
Например, формы «1» и «2» платформа 1С нарисовала сама:

Данные для подкастов пришлось вводить ручками, но это одноразовое действие:

Дальше пришлось немного написать кода на языке 1С. Я знаю, что многие на хабре не считают 1С нормальным языком. Но как по мне, 1С умеет делать всё, что умеют все остальные языки. И это всё «из коробки». Ребятки, сравните-ка код 1С по построчному чтению файла в старых версиях Java (статья на хабре: Эволюция Java на примере чтения строк из файла) и код 1С:
&НаКлиенте Процедура КомандаПрочитатьФайл(Команда) ЧтениеТекста = Новый ЧтениеТекста("e:\Data\Texts\Статья на хабре, новости\Attachments\30 сюжетов цивилизации RSS.xml", "UTF-8"); ТекущаяСтрока = ЧтениеТекста.ПрочитатьСтроку(); Пока ТекущаяСтрока <> Неопределено Цикл // Обработать строку ТекущаяСтрока = ЧтениеТекста.ПрочитатьСтроку(); КонецЦикла; КонецПроцедуры
Но извините, я отвлёкся.
Кода на 1С будет не очень много:
КомандаЗагрузитьСписокАудиоматериалов — для выделенных строк. 1С подключается к RSS-ленте, загружает XML, парсит его, и добавляет новые файлы для загрузки в справочник «АудиоМатериалы». Одна новость = один файл.
Загрузка файла из интернет:
&НаСервере Процедура ЗагрузитьСписокАудиоматериаловДляПодкаста(Подкаст, URL) // 1. Загрузить XML-файл со списком аудиоматериалов. РазложенныйURL = СтрРазделить(URL, "/", Ложь); Сервер = РазложенныйURL[1]; // https://radiomayak.ru/podcasts/rss/podcast/3321/type/audio/ -> radiomayak.ru Порт = Неопределено; Пользователь = Неопределено; Пароль = Неопределено; Прокси = Новый ИнтернетПрокси(Истина); Таймаут = 30; HTTPСоединение = Новый HTTPСоединение( Сервер, Порт, Пользователь, Пароль, Прокси, Таймаут, Новый ЗащищенноеСоединениеOpenSSL, Ложь); РазложенныйАдресРесурса = РазложенныйURL; РазложенныйАдресРесурса.Удалить(0); // http РазложенныйАдресРесурса.Удалить(0); // сервер АдресРесурса = СтрСоединить(РазложенныйАдресРесурса, "/"); Заголовки = Новый Соответствие; HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса, Заголовки); HTTPОтвет = HTTPСоединение.ВызватьHTTPМетод("GET", HTTPЗапрос); Если HTTPОтвет.КодСостояния = 200 Тогда ТелоОтвета = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8); //// И так далее...
Парсинг загруженного XML и сохранение в справочник «АудиоМатериалы»:
ЧтениеXML = Новый ЧтениеXML; ЧтениеXML.УстановитьСтроку(ТелоОтвета); ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML); СписокАудиоМатериаловXDTO = ОбъектXDTO.channel.ПолучитьСписок("item"); Для Каждого ТекущийЭлементXDTO Из СписокАудиоМатериаловXDTO Цикл Длительность = ТекущийЭлементXDTO.duration; ДлительностьЧас = Число(Сред(Длительность, 1, 2)); ДлительностьМин = Число(Сред(Длительность, 4, 2)); ДлительностьСек = Число(Сред(Длительность, 7, 2)); ДатаОбновления = ДатаRFC1123(ТекущийЭлементXDTO.pubDate); Описание = ?(ТекущийЭлементXDTO.Свойства().Получить("summary") = Неопределено, "", ТекущийЭлементXDTO.summary); Заголовок = ТекущийЭлементXDTO.title; УИН = ТекущийЭлементXDTO.guid.Последовательность().ПолучитьТекст(0); Гиперссылка = ТекущийЭлементXDTO.enclosure.url; РазмерФайла = ?(ТекущийЭлементXDTO.enclosure.Свойства().Получить("length") = Неопределено, 0, ТекущийЭлементXDTO.enclosure.length); // Найти элемент справочника АудиоМатериалы по УИН АудиоМатериалСсылка = Справочники.АудиоМатериалы.НайтиПоРеквизиту("УИН", УИН, , Подкаст); Если АудиоМатериалСсылка.Пустая() Тогда АудиоМатериалОбъект = Справочники.АудиоМатериалы.СоздатьЭлемент(); Иначе АудиоМатериалОбъект = АудиоМатериалСсылка.ПолучитьОбъект(); КонецЕсли; АудиоМатериалОбъект.Владелец = Подкаст; АудиоМатериалОбъект.УИН = УИН; АудиоМатериалОбъект.Наименование = Заголовок; АудиоМатериалОбъект.URL = Гиперссылка; АудиоМатериалОбъект.ДлительностьЧасов = ДлительностьЧас; АудиоМатериалОбъект.ДлительностьМинут = ДлительностьМин; АудиоМатериалОбъект.ДлительностьСекунд = ДлительностьСек; АудиоМатериалОбъект.Описание = Описание; АудиоМатериалОбъект.РазмерФайла = РазмерФайла; АудиоМатериалОбъект.ДатаОбновления = ДатаОбновления; АудиоМатериалОбъект.Записать(); КонецЦикла; ЧтениеXML.Закрыть();
Не люблю формат RSS из-за формата даты RFC 1123 (если точнее, то RFC 822, часть 5) — <pubDate>Sun, 21 May 2017 11:00:00 GMT</pubDate>. Пришлось написать ещё немного кода:
&НаСервере // Возвращает дату, преобразованную из формата RFC 1123 в тип Дата. Функция ДатаRFC1123(ДатаСтрокойHTTP) ИменаМесяцев = "janfebmaraprmayjunjulaugsepoctnovdec"; // rfc1123-date = wkday "," SP date1 SP time SP "GMT". ПозицияПервогоПробела = СтрНайти(ДатаСтрокойHTTP, " ");//с первого пробела до второго пробела идет дата. ПодстрокаДата = Сред(ДатаСтрокойHTTP,ПозицияПервогоПробела + 1); ПодстрокаВремя = Сред(ПодстрокаДата, 13); ПодстрокаДата = Лев(ПодстрокаДата, 11); ПозицияПервогоПробела = СтрНайти(ПодстрокаВремя, " "); ПодстрокаВремя = Лев(ПодстрокаВремя,ПозицияПервогоПробела - 1); // date1 = 2DIGIT SP month SP 4DIGIT. ПодстрокаДень = Лев(ПодстрокаДата, 2); ПодстрокаМесяц = Формат(Цел(СтрНайти(ИменаМесяцев,НРег(Сред(ПодстрокаДата,4,3))) / 3)+1, "ЧЦ=2; ЧН=00; ЧВН="); ПодстрокаГод = Сред(ПодстрокаДата, 8); // time = 2DIGIT ":" 2DIGIT ":" 2DIGIT. ПодстрокаЧас = Лев(ПодстрокаВремя, 2); ПодстрокаМинута = Сред(ПодстрокаВремя, 4, 2); ПодстрокаСекунда = Прав(ПодстрокаВремя, 2); Возврат Дата(ПодстрокаГод + ПодстрокаМесяц + ПодстрокаДень + ПодстрокаЧас + ПодстрокаМинута + ПодстрокаСекунда); КонецФункции
После того, как мы сохранили в таблице список URL mp3-файлов, можно их загрузить. Если запустить 1С в режиме «Предприятие», то в справочнике «Подкасты» можно выделить несколько строк и нажать «Загрузить аудиоматериалы».
КомандаЗагрузитьАудиоматериалы — анализирует данные из справочника «АудиоМатериалы» и сравнивает с уже загруженными файлами в файловой системе. Если файла нет или размер не совпадает, то он будет загружен.
Данные в можно получать запросами, очень похожими на обычный SQL:
Запрос = Новый Запрос; Запрос.Текст = " |ВЫБРАТЬ | ЛОЖЬ КАК Загружать, | Спр.Владелец.Наименование КАК Подкаст, | &КаталогМедиаФайлов КАК КаталогМедиаФайлов, | Спр.Владелец.КаталогСохраненияАудиоматериалов КАК КаталогСохраненияАудиоматериалов, | Спр.Владелец.ШаблонИмениФайла КАК ШаблонИмениФайла, | &Строка255 КАК ИмяФайла, | Спр.Наименование КАК Наименование, | Спр.URL КАК URL, | Спр.Описание КАК Описание, | Спр.ДатаОбновления КАК ДатаОбновления, | "" "" КАК ДатаОбновленияГГГГММДД, | Спр.ДлительностьЧасов КАК ДлительностьЧасов, | Спр.ДлительностьМинут КАК ДлительностьМинут, | Спр.ДлительностьСекунд КАК ДлительностьСекунд, | "" "" КАК ДлительностьММСС, | Спр.РазмерФайла КАК РазмерФайлаНадо, | 0 КАК РазмерФайлаЕсть |ИЗ | Справочник.АудиоМатериалы КАК Спр |ГДЕ | Спр.Владелец В (&Подкасты) | И Спр.Владелец.ПометкаУдаления = ЛОЖЬ |УПОРЯДОЧИТЬ ПО | Спр.Владелец.Наименование |"; Запрос.УстановитьПараметр("Подкасты" , МассивПодкастов); Запрос.УстановитьПараметр("Строка255" , Строка255); Запрос.УстановитьПараметр("КаталогМедиаФайлов", КаталогМедиаФайлов); РезультатЗапроса = Запрос.Выполнить(); Если НЕ РезультатЗапроса.Пустой() Тогда // Обработка данных запроса КонецЕсли;
Хэдхантеры, вы вообще в курсе, что даже начинающий «1С-ник из коробки» уже умеет SQL?
Проверяем, наличие файлов. Если файл есть и его размер совпадает, то загружать заново смысла нет. Если файла нет или его размер не совпадает — загрузим снова.
// Подготовить имена файлов ТаблицаФайлов = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.Прямой); Для Каждого ТекущийФайл Из ТаблицаФайлов Цикл Если СтрЗаканчиваетсяНа(ТекущийФайл.КаталогМедиаФайлов, "\") Тогда ТекущийФайл.КаталогМедиаФайлов = Лев(ТекущийФайл.КаталогМедиаФайлов, СтрДлина(ТекущийФайл.КаталогМедиаФайлов) - 1); КонецЕсли; Если СтрЗаканчиваетсяНа(ТекущийФайл.КаталогСохраненияАудиоматериалов, "\") Тогда ТекущийФайл.КаталогСохраненияАудиоматериалов = Лев(ТекущийФайл.КаталогСохраненияАудиоматериалов, СтрДлина(ТекущийФайл.КаталогСохраненияАудиоматериалов) - 1); КонецЕсли; ТекущийФайл.ДатаОбновленияГГГГММДД = Формат(ТекущийФайл.ДатаОбновления, "ДФ=yyyy-MM-dd"); ТекущийФайл.ДлительностьММСС = Формат(ТекущийФайл.ДлительностьМинут, "ЧЦ=2; ЧН=00; ЧВН=") + "." + Формат(ТекущийФайл.ДлительностьСекунд, "ЧЦ=2; ЧН=00; ЧВН="); ТекущийФайл.КаталогСохраненияАудиоматериалов = ЗаменитьПеременные(ТекущийФайл.КаталогСохраненияАудиоматериалов, ТекущийФайл, ПравилаЗамены); ТекущийФайл.ИмяФайла = ЗаменитьПеременные(ТекущийФайл.ШаблонИмениФайла, ТекущийФайл, ПравилаЗамены); ТекущийФайл.ИмяФайла = УдалитьЗапрещенныеСимволы(ТекущийФайл.ИмяФайла); КонецЦикла; // Проверить файлы на наличие и размер. // Параллельно проверить и сформировать структуру каталогов. Для Каждого ТекущийФайл Из ТаблицаФайлов Цикл Файл = Новый Файл(ТекущийФайл.КаталогСохраненияАудиоматериалов + "\" + ТекущийФайл.ИмяФайла); Если Файл.Существует() Тогда ТекущийФайл.РазмерФайлаЕсть = Файл.Размер(); Если ТекущийФайл.РазмерФайлаЕсть <> ТекущийФайл.РазмерФайлаНадо Тогда ТекущийФайл.Загружать = Истина; КонецЕсли; Иначе СтруктураКаталогов = СтрРазделить(ТекущийФайл.КаталогСохраненияАудиоматериалов + "\" + ТекущийФайл.ИмяФайла, "\", Ложь); ТекущееИмяКаталога = СтруктураКаталогов[0]; Для С=1 По СтруктураКаталогов.ВГраница()-1 Цикл // Без имени диска и без самого имени файла. ТекущееИмяКаталога = ТекущееИмяКаталога + "\" + СтруктураКаталогов[С]; ТекущийКаталог = Новый Файл(ТекущееИмяКаталога); Если НЕ ТекущийКаталог.Существует() Тогда СоздатьКаталог(ТекущееИмяКаталога); КонецЕсли; КонецЦикла; ТекущийФайл.Загружать = Истина; КонецЕсли; КонецЦикла;
// Загрузить несуществующие файлы. Для Каждого ТекущийФайл Из ТаблицаФайлов Цикл Если ТекущийФайл.Загружать = Истина Тогда ЗагрузитьФайл(ТекущийФайл.URL, ТекущийФайл.КаталогСохраненияАудиоматериалов + "\" + ТекущийФайл.ИмяФайла); ОбновитьОписаниеФайла(ТекущийФайл.ИмяФайла, ТекущийФайл.КаталогСохраненияАудиоматериалов, ТекущийФайл.Описание); КонецЕсли; КонецЦикла;
Непосредственно загрузка:
&НаСервере Процедура ЗагрузитьФайл(URL, ПолноеИмяФайла) РазложенныйURL = СтрРазделить(URL, "/", Ложь); Сервер = РазложенныйURL[1]; // https://radiomayak.ru/podcasts/rss/podcast/3321/type/audio/ -> radiomayak.ru Порт = Неопределено; Пользователь = Неопределено; Пароль = Неопределено; Прокси = Новый ИнтернетПрокси(Истина); Таймаут = 30; HTTPСоединение = Новый HTTPСоединение( Сервер, Порт, Пользователь, Пароль, Прокси, Таймаут, Новый ЗащищенноеСоединениеOpenSSL, Ложь); РазложенныйАдресРесурса = РазложенныйURL; РазложенныйАдресРесурса.Удалить(0); // http РазложенныйАдресРесурса.Удалить(0); // сервер АдресРесурса = СтрСоединить(РазложенныйАдресРесурса, "/"); Заголовки = Новый Соответствие; HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса, Заголовки); HTTPОтвет = HTTPСоединение.ВызватьHTTPМетод("GET", HTTPЗапрос); Если HTTPОтвет.КодСостояния = 200 Тогда ДвоичныеДанныеФайла = HTTPОтвет.ПолучитьТелоКакДвоичныеДанные(); ДвоичныеДанныеФайла.Записать(ПолноеИмяФайла); Иначе Сообщить( СтрШаблон( НСтр("ru='Ошибка загрузки: код %1, сервер %2, ресурс %3'"), HTTPОтвет.КодСостояния, Сервер, АдресРесурса)); КонецЕсли; КонецПроцедуры
В качестве файлового менеджера я использую «Total commander». Купил его официально, но в принципе программа работает и бесплатно — всего-навсего при запуске программы надо будет нажать одну из трёх случайных кнопок.
В «Total commander» в каталоге можно сохранить файл «descript.ion», в котором можно хранить комментарии к файлам. Это очень удобно. Эти комментарии в отдельном файле (в отличие от потоков в NTFS) сохраняются при копировании на FAT (естественно, если копировать с помощью «Total Commander»). Некоторые умельцы даже умеют показывать такие комментарии и в стандартном проводнике Windows (https://dudom.ru/kompjutery/kak-dobavit-kommentarij-k-fajlu/), но я не пробовал.
Например, в комментарии можно хранить некие тэги, например «Просмотрено;» и настроить сам «Total commander», чтобы файлы помеченные таким тэгом показывались серым цветом (скриншот будет ниже). Удобно.
Структура файла «descript.ion» очень простая: имя файла (возможно, в кавычках) и через пробел — произвольный комментарий:

Поэтому, при загрузке файла, можно сразу делать запись в этот «descript.ion»:
&НаСервере Процедура ОбновитьОписаниеФайла(ИмяФайла, КаталогСохраненияАудиоматериалов, Описание) // Найти / создать в КаталогСохраненияАудиоматериалов файл descript.ion ИмяФайлаОписания = КаталогСохраненияАудиоматериалов + "\descript.ion"; ФайлОписаний = Новый Файл(ИмяФайлаОписания); Если ФайлОписаний.Существует() Тогда ЧтениеТекста = Новый ЧтениеТекста(ИмяФайлаОписания, КодировкаТекста.ANSI, Символы.ПС, Символы.ПС, Ложь); ВсеСодержимое = ЧтениеТекста.Прочитать(); ЧтениеТекста.Закрыть(); Иначе ВсеСодержимое = ""; КонецЕсли; // Найти / добавить в файле КаталогСохраненияАудиоматериалов\descript.ion строку, начинающуюся с ИмяФайла и содержащую Описание (замена переводов строк на \n) ВсеНовыеСтроки = Новый Массив; ОписаниеБезПереводовСтрок = Описание; ОписаниеБезПереводовСтрок = СтрЗаменить(ОписаниеБезПереводовСтрок, "<br>", "\n"); ОписаниеБезПереводовСтрок = СтрЗаменить(ОписаниеБезПереводовСтрок, "<br/>", "\n"); ОписаниеБезПереводовСтрок = СтрЗаменить(ОписаниеБезПереводовСтрок, Символы.ПС, "\n"); ОписаниеБезПереводовСтрок = СтрЗаменить(ОписаниеБезПереводовСтрок, Символы.ВК, "\n"); ОписаниеБезПереводовСтрок = СтрЗаменить(ОписаниеБезПереводовСтрок, "\n\n", "\n"); Если НЕ ПустаяСтрока(ВсеСодержимое) Тогда НайденТекущийФайл = Ложь; ВсеСтарыеСтроки = СтрРазделить(ВсеСодержимое, Символы.ПС, Ложь); Для Каждого ТекущаяСтрока Из ВсеСтарыеСтроки Цикл Если СтрНачинаетсяС(ТекущаяСтрока, """" + ИмяФайла + """" + " ") Тогда ВсеНовыеСтроки.Добавить("""" + ИмяФайла + """" + " " + ОписаниеБезПереводовСтрок); НайденТекущийФайл = Истина; Иначе ВсеНовыеСтроки.Добавить(ТекущаяСтрока); КонецЕсли; КонецЦикла; Если НайденТекущийФайл <> Истина Тогда ВсеНовыеСтроки.Добавить("""" + ИмяФайла + """" + " " + ОписаниеБезПереводовСтрок); КонецЕсли; Иначе ВсеНовыеСтроки.Добавить("""" + ИмяФайла + """" + " " + ОписаниеБезПереводовСтрок); КонецЕсли; // Записать в файл обратно. Если ВсеНовыеСтроки.Количество() > 0 Тогда ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаОписания, КодировкаТекста.ANSI, Символы.ПС, Ложь, Символы.ПС); ЗаписьТекста.Записать(СтрСоединить(ВсеНовыеСтроки, Символы.ПС)); ЗаписьТекста.Закрыть(); КонецЕсли; КонецПроцедуры
А вот и скачанные файлы, которые можно просто скопировать на плеер:

Обратите внимание, что если в комментарии к файлу есть «Просмотрено;», то он показывается серым цветом шрифта. «Total commander» умеет выделять файлы цветом по разным условиям (атрибуты файла, размер, наличие текста в комментарии, плагины), что очень удобно. По логике, конечно же, надо было бы назвать тэг «Прослушано;», а не «Просмотрено», но это просто устоявшийся у меня порядок, менять который — лениво. Извините.
Если кому интересно — можно выложить эту базу 1С в общий доступ, но к сожалению на хабре нельзя приаттачивать файлы к статье (или я не разобрался?).
Размер только метаданных (1cv8.cf) — 18 051 байт.
Размер выгруженной и сжатой базы (данные + метаданные, 1cv8.dt) — 662 650 байт.
Размер базы на диске (1Cv8.1CD) — 9 601 024 байт.
Честно говоря, не понял, как удобнее было бы выложить и надо ли это делать вообще? Прикрутил голосовалку.
Какая была цель у этих статей? Продвинуть какую-то технологию или программу? Реклама? Поделиться опытом? Пусть это будет «поделиться опытом».
И в завершение:
-
Не стесняйтесь экспериментировать;
-
Изменяйте мир в лучшую сторону;
-
И не забывайте делиться своим опытом, чтобы другие тоже могли изменять мир в лучшую сторону.
ссылка на оригинал статьи https://habr.com/ru/post/551836/
Добавить комментарий