Alexander Speshilov ([info]speshuric) wrote,
@ 2007-09-04 09:42:00
Previous Entry  Add to memories!  Tell a Friend  Next Entry
Entry tags:

Работа с бинарными файлами в 1С 8
В системе 1С практически невозможно работать с массивами двоичных данных. Ну очень тщательно разработчики платформы оградили программистов прикладных решений от нюансов реализации. Так, например, даже задача прочитать нетекстовый (бинарный) файл и проанализировать его содержимое, а также задача записать такой файл не решаются штатными средствами. А иногда это нужно.

Процедура Пример(ИмяФайла)

    // Перечисления из библиотеки ADO
    StreamTypeEnum = Новый Структура("adTypeBinary, adTypeText", 1, 2);
    ConnectModeEnum = Новый Структура(
        "adModeRead, adModeReadWrite, adModeRecursive, adModeShareDenyNone,
        |adModeShareDenyRead, adModeShareDenyWrite, adModeShareExclusive, 
        |adModeUnknown, adModeWrite", 1, 3, 4194304, 16, 4, 8, 12, 0, 2);
    SaveOptionsEnum = Новый Структура("adSaveCreateNotExist, adSaveCreateOverWrite", 1, 2);
    
    StreamIn = Новый COMОбъект("ADODB.Stream"); //Для создания этого объекта требуется MDAC 2.5 и выше
    StreamIn.Type = StreamTypeEnum.adTypeBinary;
    
    StreamIn.Open(); //По умолчанию открывается на чтение
    StreamIn.LoadFromFile(ИмяФайла); //Очевидно, что для больших файлов так поступать нехорошо.
    Data = StreamIn.Read(); //у переменной Data тип COMSafeArray, это массив байтов
    StreamIn.Close(); //Больше нам этот поток не нужен - закрываем.
    
    //Конечно, манипуляция в памяти приемлима только для небольших файлов!
    СодержимоеМассив = Data.Выгрузить();
    
    //...
    //...
    //тут можно по-всякому поиздеваться над массивом
    //...
    //...
    
    //Запихиваем массив 1С в COMSafeArray. VT_UI1 - обозначение однобайтного беззнакового целого.
    Data = Новый COMSafeArray(СодержимоеМассив, "VT_UI1", СодержимоеМассив.Количество());
    
    StreamOut = Новый COMОбъект("ADODB.Stream");
    StreamOut.Type = StreamTypeEnum.adTypeBinary;
    StreamOut.Mode = ConnectModeEnum.adModeReadWrite; //Нужны и чтение и запись.
    
    StreamOut.Open(); //Открыли на чтение и запись
    StreamOut.Write(Data); 
    StreamOut.SaveToFile(ИмяФайла, SaveOptionsEnum.adSaveCreateOverWrite); //"2" - перезапись файла
    StreamOut.Close();

КонецПроцедуры



(18 comments) - (Post a new comment)


[info]lamer19
2007-09-04 04:39 am UTC (link)
Под 7.7 была какая то компонента работы с двоичными файлами.

(Reply to this) (Thread)


[info]speshuric
2007-09-04 05:00 am UTC (link)
Ну в 7.7 может и была. Может она даже подходит для 8. Но для такой фигни писать ВК - это ж муть бессмысленная. Собственно ВК нужны были в 7.7 чтобы обрабатывать события от ВК (так драйверы оборудования работали) и чтобы контекст приложения брать (так, например, прямые запросы на SQL запускались). Ну и "многоязычность" внешних компонент еще.
Во всём остальном - это лишняя прокладка между COM и 1С. А учитывая, что мне давно лень писать на чём-то кроме C# и 1С (ну изредка еще VBS, но не люблю я это дело), то получается бутерброд еще и из CLR. Ужас :)

В 8 большого смысла ВК нет. Контекст, если надо будет - передам как-нибудь. Для подключения к событиям появилась "ДобавитьОбработчик". Писать обёртки вокруг стандартного API не надо. В том, что MDAC как минимум 2.8 установлен на 90% машин - я уверен. Если будет недостаточно производительности - запихну часть работы в свой COM-объект, написанный на том же C#.

(Reply to this) (Parent)


[info]danfe
2007-09-04 05:19 am UTC (link)
Бох ты мой, сколько magic constants. ;-)

(Reply to this) (Thread)


[info]speshuric
2007-09-04 05:31 am UTC (link)
Данфе, мне просто было лень все их переписывать. Они определены как константы в соответствующих перечислениях в COM, но этого не видно из 1С. Видны только сами классы, к сожалению. Да и ладно тебе насчет "много". Аж целых 2. Когда пишешь, например, на том же VB/VBS (да и CLR) приложение напрямую дёргающее функции Win32 API, то картина зачастую похожая - приходится объявлять то, что объявлено в хедерных файлах, но что полностью отсутствует в COM библиотеках.
Если хочешь, то специально для тебя я увеличу пример примерно на 20 строк и объявлю все константы через структуры. Но мне это нахер не надо.

(Reply to this) (Parent)(Thread)


[info]danfe
2007-09-04 06:12 am UTC (link)
Шурик, да верю я, что это косяк 1С, а не твоя неряшливость, право же. И смайлег там не просто так был поставлен.

(Reply to this) (Parent)(Thread)


[info]speshuric
2007-09-04 06:17 am UTC (link)
Ты не понял. 1С тут почти не причём. Если что в Visual Studio 7.0 во времена начала .NET были подобные проблемы (не всё хорошо и красиво автоматически импортировалось из COM в CLR и приходилось изъёбываться с несколько нетипичной передачей параметров). Сейчас там всё, естественно, лучше. И в VB - тоже была проблема с перечислениями из Win32API (если не было под рукой файла с нужной декларацией).

(Reply to this) (Parent)(Thread)


[info]danfe
2007-09-04 06:21 am UTC (link)
А, ну я просто про "косяк 1С" подумал из-за "но этого не видно из 1С".

(Reply to this) (Parent)(Thread)


[info]speshuric
2007-09-04 06:27 am UTC (link)
Назовём это не "косяк", а "ограниченная поддержка COM" :)

ЗЫ: Знаешь, по сравнению с тем, что раньше нельзя было прицепиться к событиям от COM-объектов, теперь уже всё просто замечательно. Но есть куда расти. Например, интеграция с CLR - это было бы шикарно и полезно.

(Reply to this) (Parent)


[info]speshuric
2007-09-04 06:13 am UTC (link)
Специально для тебя поправил ;-)

(Reply to this) (Parent)


(Anonymous)
2007-12-13 08:30 am UTC (link)
Пасиб, очень помогло!!

(Reply to this)


(Anonymous)
2008-04-14 01:13 pm UTC (link)
Большой Сенкс!Очень помогло!

(Reply to this) (Thread)


(Anonymous)
2009-03-13 02:01 pm UTC (link)
У вас я нашел то, что надо!! СПАСИБО!!!

(Reply to this) (Parent)


(Anonymous)
2009-03-24 10:19 am UTC (link)
А как быть с V7.7?
Там не работает :(
Спотыкается на строчке:
Data = StreamIn.Read(); //у переменной Data тип COMSafeArray, это массив байтов

(Reply to this)

Спасибо
(Anonymous)
2009-04-07 10:36 am UTC (link)
сильно помог

(Reply to this)


(Anonymous)
2009-05-22 07:11 am UTC (link)
А не подскажете, как этот COMSafeArray запихать в поле скульной таблицы?

(Reply to this) (Thread)


[info]speshuric
2009-05-23 04:01 am UTC (link)
прям-таки в поле? Наверное, только сериализовав в XML или еще каким макаром.

(Reply to this) (Parent)(Thread)


(Anonymous)
2009-05-25 05:17 am UTC (link)
Разобрался. Вот, может кому пригодится:

Поток=Новый COMОбъект("ADODB.Stream");
Поток.Type=1;
Поток.Open();
Поток.LoadFromFile("какой-то файл");
// Подключение к источнику данных
Попытка
Connection.Open(СтрокаПодключения);
Исключение
Сообщить(ОписаниеОшибки()) ;
Возврат;
КонецПопытки;

RecordSet = Новый COMОбъект("ADODB.RecordSet");
RecordSet.ActiveConnection=Connection;
RecordSet.CursorType = 1;
RecordSet.LockType = 3;

RecordSet.Open("
| SELECT *
| from
| table1");

RecordSet.fields("file").Value=Поток.Read();

RecordSet.Update();
RecordSet.Close();

Примерно как-то так.

(Reply to this) (Parent)(Thread)


(Anonymous)
2009-05-25 05:18 am UTC (link)
И еще: работает не очень шустро:(

(Reply to this) (Parent)


(18 comments) - (Post a new comment)

Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…