Извлечь максимум из новостей в интернете, часть 3

от автора

Часть 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *